<commit_before>// Kevin Cantu
// Boyer-Moore string searching

use std;

// Function: findn
//
// Boyer-Moore string search, which returns
// up to `nn` byte positions of matched substrings
fn findn (needle: str, haystack: str, nn: uint) -> [uint] {

   let results = [];

   // empty haystack
   if str::len(haystack) == 0u {
      ret results;
   }

   // empty needle
   if str::len(needle) == 0u {
      vec::push(results, 0u);
      ret results;
   }

   // needle too large
   if str::len(haystack) < str::len(needle) {
      ret results;
   }

   // generate the tables
   let ct = char_table(needle);
   let pt = prefix_table(needle);

   // simplify the table referencing
   let getShift = fn@(pos: uint) -> uint {
      let charShift, prefShift; // also: ct, pt, needle

      assert needle != "";
      assert pos >= 0u;
      assert pos < str::len(needle);

      alt ct.find(needle[pos] as uint) {
         option::none    { charShift = str::len(needle);}
         option::some(x) { charShift = x;}
      }

      let offset = str::len(needle) - pos;

      assert offset >= 0u;
      assert offset < str::len(needle);

      alt pt.find(offset) {
         option::none { fail "something is out of range" }
         option::some(x) { prefShift = x;}
      }

      std::io::println(#fmt("<charShift: %u, prefShift: %u>", charShift, prefShift));
      ret greaterOf(charShift, prefShift);
   };

   let outerLim  = str::len(haystack);
   let windowLim = str::len(needle);

   // step up through the haystack
   let outerii = 0u;
   while outerii < outerLim - windowLim + 1u {

      // step back through needle
      let windowii = windowLim;
      while 0u < windowii
            && (outerii + (windowii - 1u)) < outerLim  // don't exceed haystack
      {
         windowii -= 1u;

         std::io::println(#fmt("%c@%u =? %c@%u",
                          needle[windowii] as char,
                          windowii,
                          haystack[outerii+windowii] as char,
                          outerii + windowii));

         // if still matching
         if needle[windowii] == haystack[outerii+windowii] {

            // if full match
            if windowii == 0u {
               std::io::println(#fmt("[pushing %u]", outerii));
               vec::push(results, outerii);

               if vec::len(results) >= nn {
                  ret results;
               } else {
                  outerii += windowLim;
               }
            }

         // if partial match
         } else {
            let shift = getShift(windowii);

            outerii += shift;
            break;
         }
      }
   }

   ret results;
}

fn char_table (needle: str) -> std::map::map<uint, uint> {
   let mm: std::map::map<uint, uint> = std::map::new_uint_hash();
   let len = str::len(needle);

   let jj = len - 1u; // drop the last byte

   assert jj >= 0u;
   assert jj < str::len(needle);

   // from last-1 to first
   while jj > 0u {
      jj -= 1u;
      if ! mm.contains_key(needle[jj] as uint) {
         // store reverse indexes
         mm.insert(needle[jj] as uint, len - 1u - jj);
      }
   }

   ret mm;
}

//#[test]
fn test_char_table () {
   let ct = char_table("ANPANMAN");
   assert 1u == ct.get('A' as uint); assert 2u == ct.get('M' as uint);
   assert 3u == ct.get('N' as uint);
   assert 5u == ct.get('P' as uint);
   assert option::none == ct.find('z' as uint);
}

fn prefix_table (needle: str) -> std::map::map<uint, uint> unsafe {
   let mm: std::map::map<uint, uint> = std::map::new_uint_hash();

   // WAIT, HOW IS THIS ALLOWED TO MUTATE mm?
   let fill = fn@(kk: uint, vv: uint) {
      if ! mm.contains_key(kk) {
         mm.insert(kk, vv);
         std::io::println(#fmt("%u => %u", kk, vv));
      }
   };

   let lim   = str::len(needle);
   assert 0u < lim;

   // step to larger suffixes
   let sii = 0u;
   while sii < lim {

      // tail of the needle we seek
      let suffix      = str::unsafe::slice_bytes(needle, lim - sii,      lim);
      let suffix_plus = str::unsafe::slice_bytes(needle, lim - sii - 1u, lim);
      let slen = str::len(suffix);

      // step to smaller prefixes
      let pii = lim - 1u;
      while pii > 0u {

         // a prefix of the needle that might be matched by
         // a partial match of a suffix
         // (which we might want to jump to)
         let prefix = str::unsafe::slice_bytes(needle, 0u, pii);

         //let msg  = "<"+suffix+"("+#fmt("%u",sii)+")";
         //let msg2 = prefix+"("+#fmt("%u",pii)+")>";
         let msg  = "<suf("+#fmt("%u",sii)+")";
         let msg2 = "pref("+#fmt("%u",pii)+")>";
         std::io::println(msg + " × " + msg2);

         // suffix might be fully matched
         let is_suffix_matched =
            str::ends_with(prefix, suffix)
            && !str::ends_with(prefix, suffix_plus)
            &&  slen < str::len(prefix);

         // prefix is bigger than suffix, only tail can match
         let is_suffix_partially_matched =
            str::len(prefix) <= str::len(suffix)
            && str::ends_with(suffix, prefix);

         if is_suffix_matched || is_suffix_partially_matched {
            fill(sii, lim-pii);
         }

         pii -= 1u;
      }

      // no matching prefix
      fill(sii, lim-pii);

      sii += 1u;
   }

   ret mm;
}

//#[test]
fn test_prefix_table_ascii() {
   let pt = prefix_table("ANPANMAN");
                            //      ... 8

   assert 1u == pt.get(0u); //        (n)
   assert 8u == pt.get(1u); //       (a)n
   assert 3u == pt.get(2u); //      (m)an
   assert 6u == pt.get(3u); //     (n)man
   assert 6u == pt.get(4u); //    (a)nman
   assert 6u == pt.get(5u); //   (p)anman
   assert 6u == pt.get(6u); //  (n)panman
   assert 6u == pt.get(7u); // (a)npanman
   //assert 0u == pt.get(8u); // fail
}

//#[test]
fn test_prefix_table_utf8() {
   let pt = prefix_table("ประเ");

   assert  1u == pt.get(0u);
   assert 12u == pt.get(3u);
   assert 12u == pt.get(6u);
   assert 12u == pt.get(9u);
}

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

// prefixes, smallest first
fn prefixes(ss: str) -> [str] unsafe {
   let vv = [];

   vec::push(vv, "");
   str::chars_iteri(ss) {|ii, _bb|
      vec::push(vv, str::slice(ss, 0u, ii+1u));
   }

   ret vv;
}

//#[test]
fn test_prefs() {
   assert ["", "a", "ab", "abc", "abcd"] == prefixes("abcd");
   assert [""] == prefixes("");
}

// suffixes, largest first
fn suffixes(ss: str) -> [str] unsafe {
   let vv = [];
   let lim = str::len(ss);

   str::chars_iteri(ss) {|ii, _bb|
      vec::push(vv, str::slice(ss, ii, lim));
   }
   vec::push(vv, "");

   ret vv;
}

//#[test]
fn test_sufs() {
   assert ["abcd", "bcd", "cd", "d", ""] == suffixes("abcd");
   assert [""] == suffixes("");
}

fn greaterOf(a: uint, b: uint) -> uint {
   if a > b { ret a; } else { ret b; }
}

//#[test]
fn test_greaterOf() {
   assert greaterOf(15u, 17u) == 17u;
   assert greaterOf(17u, 15u) == 17u;
}

fn find_(needle: str, haystack: str) -> option<uint> {
   let found = findn(needle, haystack, 1u);

   alt vec::len(found) {
      0u { option::none }
      xx { option::some(found[0u]) }
   }
}

#[test]
fn test_findn() {
   assert [] == findn("banana", "apple pie", 1u);
  assert (findn("abc", "abcxxxxxx", 1u) == [0u]);
  assert (findn("abc", "xxxabcxxx", 1u) == [3u]);
  assert (findn("abc", "xxxxxxabc", 1u) == [6u]);
  assert (findn("abc", "xxxabcabc", 1u) == [3u]);
  assert (findn("abc", "xxxabcabc", 5u) == [3u, 6u]);
  assert (findn("abc", "xxxabcxxabc", 5u) == [3u, 8u]);  // aha
}

//#[test]
fn test_find_ascii() {
  assert (find_("banana", "apple pie") == option::none);
  assert (find_("", "") == option::none);
  assert (find_("abc", "abcxxxxxx") == option::some(0u));
  assert (find_("abc", "xxxabcxxx") == option::some(3u));
  assert (find_("abc", "xxxxxxabc") == option::some(6u));
}

//#[test]
fn test_find_utf8() {
  let data = "ประเทศไทย中华Việt Nam";
  assert (find_("", data)     == option::some( 0u));
  assert (find_("ประเ", data) == option::some( 0u));
  assert (find_("ะเ", data)   == option::some( 6u));
  assert (find_("ไท华", data) == option::none);
}

#[test]
fn test_find_B() {
  let data = "ประเทศไทย中华Việt Nam";
  assert (find_("中华", data) == option::some(30u));
}

<commit_msg>well, that is another bug fixed...<commit_after>// Kevin Cantu
// Boyer-Moore string searching

use std;

// Function: findn
//
// Boyer-Moore string search, which returns
// up to `nn` byte positions of matched substrings
fn findn (needle: str, haystack: str, nn: uint) -> [uint] {

   let results = [];

   // empty haystack
   if str::len(haystack) == 0u {
      ret results;
   }

   // empty needle
   if str::len(needle) == 0u {
      vec::push(results, 0u);
      ret results;
   }

   // needle too large
   if str::len(haystack) < str::len(needle) {
      ret results;
   }

   // generate the tables
   let ct = char_table(needle);
   let pt = prefix_table(needle);

   // simplify the table referencing
   let getShift = fn@(pos: uint) -> uint {
      let charShift, prefShift; // also: ct, pt, needle

      assert needle != "";
      assert pos >= 0u;
      assert pos < str::len(needle);

      alt ct.find(needle[pos] as uint) {
         option::none    { charShift = str::len(needle);}
         option::some(x) { charShift = x;}
      }

      let offset = str::len(needle) - pos;

      assert offset >= 0u;
      assert offset < str::len(needle);

      alt pt.find(offset) {
         option::none { fail "something is out of range" }
         option::some(x) { prefShift = x;}
      }

      std::io::println(#fmt("<charShift: %u, prefShift: %u>", charShift, prefShift));
      ret greaterOf(charShift, prefShift);
   };

   let outerLim  = str::len(haystack);
   let windowLim = str::len(needle);

   // step up through the haystack
   let outerii = 0u;
   while outerii < outerLim - windowLim + 1u {

      // step back through needle
      let windowii = windowLim;
      while 0u < windowii
            && (outerii + (windowii - 1u)) < outerLim  // don't exceed haystack
      {
         windowii -= 1u;

         std::io::println(#fmt("%c@%u =? %c@%u",
                          needle[windowii] as char,
                          windowii,
                          haystack[outerii+windowii] as char,
                          outerii + windowii));

         // if still matching
         if needle[windowii] == haystack[outerii+windowii] {

            // if full match
            if windowii == 0u {
               std::io::println(#fmt("[pushing %u]", outerii));
               vec::push(results, outerii);

               if vec::len(results) >= nn {
                  ret results;
               } else {
                  outerii += windowLim;
               }
            }
         } else {
            outerii +=
               if windowii == windowLim - 1u {
                  // not matching yet
                  1u
               } else {
                  // partial match
                  getShift(windowLim - windowii)
               };

            break;
         }
      }
   }

   ret results;
}

fn char_table (needle: str) -> std::map::map<uint, uint> {
   let mm: std::map::map<uint, uint> = std::map::new_uint_hash();
   let len = str::len(needle);

   let jj = len - 1u; // drop the last byte

   assert jj >= 0u;
   assert jj < str::len(needle);

   // from last-1 to first
   while jj > 0u {
      jj -= 1u;
      if ! mm.contains_key(needle[jj] as uint) {
         // store reverse indexes
         mm.insert(needle[jj] as uint, len - 1u - jj);
      }
   }

   ret mm;
}

//#[test]
fn test_char_table () {
   let ct = char_table("ANPANMAN");
   assert 1u == ct.get('A' as uint);
   assert 2u == ct.get('M' as uint);
   assert 3u == ct.get('N' as uint);
   assert 5u == ct.get('P' as uint);
   assert option::none == ct.find('z' as uint);
}

fn prefix_table (needle: str) -> std::map::map<uint, uint> unsafe {
   let mm: std::map::map<uint, uint> = std::map::new_uint_hash();

   // WAIT, HOW IS THIS ALLOWED TO MUTATE mm?
   let fill = fn@(kk: uint, vv: uint) {
      if ! mm.contains_key(kk) {
         mm.insert(kk, vv);
         std::io::println(#fmt("%u => %u", kk, vv));
      }
   };

   let lim   = str::len(needle);
   assert 0u < lim;

   // step to larger suffixes
   let sii = 0u;
   while sii < lim {

      // tail of the needle we seek
      let suffix      = str::unsafe::slice_bytes(needle, lim - sii,      lim);
      let suffix_plus = str::unsafe::slice_bytes(needle, lim - sii - 1u, lim);
      let slen = str::len(suffix);

      // step to smaller prefixes
      let pii = lim - 1u;
      while pii > 0u {

         // a prefix of the needle that might be matched by
         // a partial match of a suffix
         // (which we might want to jump to)
         let prefix = str::unsafe::slice_bytes(needle, 0u, pii);

         //let msg  = "<"+suffix+"("+#fmt("%u",sii)+")";
         //let msg2 = prefix+"("+#fmt("%u",pii)+")>";
         let msg  = "<suf("+#fmt("%u",sii)+")";
         let msg2 = "pref("+#fmt("%u",pii)+")>";
         std::io::println(msg + " × " + msg2);

         // suffix might be fully matched
         let is_suffix_matched =
            str::ends_with(prefix, suffix)
            && !str::ends_with(prefix, suffix_plus)
            &&  slen < str::len(prefix);

         // prefix is bigger than suffix, only tail can match
         let is_suffix_partially_matched =
            str::len(prefix) <= str::len(suffix)
            && str::ends_with(suffix, prefix);

         if is_suffix_matched || is_suffix_partially_matched {
            fill(sii, lim-pii);
         }

         pii -= 1u;
      }

      // no matching prefix
      fill(sii, lim-pii);

      sii += 1u;
   }

   ret mm;
}

//#[test]
fn test_prefix_table_ascii() {
   let pt = prefix_table("ANPANMAN");
                            //      ... 8

   assert 1u == pt.get(0u); //        (n)
   assert 8u == pt.get(1u); //       (a)n
   assert 3u == pt.get(2u); //      (m)an
   assert 6u == pt.get(3u); //     (n)man
   assert 6u == pt.get(4u); //    (a)nman
   assert 6u == pt.get(5u); //   (p)anman
   assert 6u == pt.get(6u); //  (n)panman
   assert 6u == pt.get(7u); // (a)npanman
   //assert 0u == pt.get(8u); // fail
}

//#[test]
fn test_prefix_table_utf8() {
   let pt = prefix_table("ประเ");

   assert  1u == pt.get(0u);
   assert 12u == pt.get(3u);
   assert 12u == pt.get(6u);
   assert 12u == pt.get(9u);
}

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

// prefixes, smallest first
fn prefixes(ss: str) -> [str] unsafe {
   let vv = [];

   vec::push(vv, "");
   str::chars_iteri(ss) {|ii, _bb|
      vec::push(vv, str::slice(ss, 0u, ii+1u));
   }

   ret vv;
}

//#[test]
fn test_prefs() {
   assert ["", "a", "ab", "abc", "abcd"] == prefixes("abcd");
   assert [""] == prefixes("");
}

// suffixes, largest first
fn suffixes(ss: str) -> [str] unsafe {
   let vv = [];
   let lim = str::len(ss);

   str::chars_iteri(ss) {|ii, _bb|
      vec::push(vv, str::slice(ss, ii, lim));
   }
   vec::push(vv, "");

   ret vv;
}

//#[test]
fn test_sufs() {
   assert ["abcd", "bcd", "cd", "d", ""] == suffixes("abcd");
   assert [""] == suffixes("");
}

fn greaterOf(a: uint, b: uint) -> uint {
   if a > b { ret a; } else { ret b; }
}

//#[test]
fn test_greaterOf() {
   assert greaterOf(15u, 17u) == 17u;
   assert greaterOf(17u, 15u) == 17u;
}

fn find_(needle: str, haystack: str) -> option<uint> {
   let found = findn(needle, haystack, 1u);

   alt vec::len(found) {
      0u { option::none }
      xx { option::some(found[0u]) }
   }
}

//#[test]
fn test_findn() {
   assert [] == findn("banana", "apple pie", 1u);
   assert (findn("abc", "abcxxxxxx", 1u) == [0u]);
   assert (findn("abc", "xxxabcxxx", 1u) == [3u]);
   assert (findn("abc", "xxxxxxabc", 1u) == [6u]);
   assert (findn("abc", "xxxabcabc", 1u) == [3u]);
   assert (findn("abc", "xxxabcabc", 5u) == [3u, 6u]);
   assert (findn("abc", "xxxabcxabc", 5u) == [3u, 7u]);
   assert (findn("abc", "xxxabcxxabc", 5u) == [3u, 8u]);
}

//#[test]
fn test_find_ascii() {
  assert (find_("banana", "apple pie") == option::none);
  assert (find_("", "") == option::none);
  assert (find_("abc", "abcxxxxxx") == option::some(0u));
  assert (find_("abc", "xxxabcxxx") == option::some(3u));
  assert (find_("abc", "xxxxxxabc") == option::some(6u));
}

//#[test]
fn test_find_utf8() {
  let data = "ประเทศไทย中华Việt Nam";
  assert (find_("", data)     == option::some( 0u));
  assert (find_("ประเ", data) == option::some( 0u));
  assert (find_("ะเ", data)   == option::some( 6u));
  assert (find_("ไท华", data) == option::none);
}

#[test]
fn test_find_B() {
  let data = "ประเทศไทย中华Việt Nam";
  assert (find_("中华", data) == option::some(30u));
}

<|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.
//!
//! [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 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.
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
//! - [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
//! [Bincode]: https://github.com/servo/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
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [Avro]: https://github.com/flavray/avro-rs
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [Postcard]: https://github.com/jamesmunns/postcard
//! [URL]: https://docs.rs/serde_qs
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: http://doc.crates.io/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.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.118")]
// 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))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// 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,
        // not available in our oldest supported compiler
        checked_conversions,
        empty_enum,
        redundant_field_names,
        redundant_static_lifetimes,
        // 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
        enum_glob_use,
        map_err_ignore,
        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.
#![forbid(unsafe_code)]
#![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, 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", collections_bound))]
    pub use std::collections::Bound;

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

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

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

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

    #[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;

#[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::*;
<commit_msg>Switch to short form for serde.rs link in rustdoc<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.
//! - [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 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.
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
//! - [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
//! [Bincode]: https://github.com/servo/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
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [Avro]: https://github.com/flavray/avro-rs
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [Postcard]: https://github.com/jamesmunns/postcard
//! [URL]: https://docs.rs/serde_qs
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: http://doc.crates.io/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.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.118")]
// 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))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// 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,
        // not available in our oldest supported compiler
        checked_conversions,
        empty_enum,
        redundant_field_names,
        redundant_static_lifetimes,
        // 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
        enum_glob_use,
        map_err_ignore,
        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.
#![forbid(unsafe_code)]
#![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, 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", collections_bound))]
    pub use std::collections::Bound;

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

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

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

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

    #[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;

#[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::*;
<|endoftext|>


<commit_before>use std::io::stdio::{stdout, stderr};
use std::io::fs::File;

use serialize::json::from_reader;
use J = serialize::json;
use argparse::{ArgumentParser, Store, List};

use super::super::env::Environ;

pub fn extract_json(_env: &mut Environ, args: Vec<String>)
    -> Result<int, String>
{
    let mut filename = Path::new(".");
    let mut columns = Vec::new();
    {
        let mut ap = ArgumentParser::new();
        ap.refer(&mut filename)
            .add_argument("filename", box Store::<Path>,
                "A JSON file to parse")
            .required();
        ap.refer(&mut columns)
            .add_argument("column", box List::<String>,
                "A columns to extract");
        match ap.parse(args, &mut stdout(), &mut stderr()) {
            Ok(()) => {}
            Err(0) => return Ok(0),
            Err(_) => return Ok(122),
        }
    }
    let mut file = try!(File::open(&filename)
        .map_err(|e| format!("Can't open file {}: {}",
                             filename.display(), e)));
    let json = try!(from_reader(&mut file)
        .map_err(|e| format!("Can't parse {}: {}", filename.display(), e)));
    let lst = match json {
        J::List(lst) => lst,
        _ => return Err(format!("Root entitity is not a list")),
    };
    let mut out = stdout();
    for obj in lst.iter() {
        let tree = match obj {
            &J::Object(ref tmap) => tmap,
            _ => return Err(format!("Not an object in a list")),
        };
        for col in columns.iter() {
            match tree.find(col) {
                Some(&J::String(ref x)) => try!(out.write_str(x.as_slice())
                    .map_err(|e| format!("Error writing to stdout: {}", e))),
                _ => {},
            };
            try!(out.write_char('\t')
                .map_err(|e| format!("Error writing to stdout: {}", e)));
        }
        try!(out.write_char('\n')
            .map_err(|e| format!("Error writing to stdout: {}", e)));
    }
    return Ok(0);
}
<commit_msg>Remove '\t' after last column<commit_after>use std::io::stdio::{stdout, stderr};
use std::io::fs::File;

use serialize::json::from_reader;
use J = serialize::json;
use argparse::{ArgumentParser, Store, List};

use super::super::env::Environ;

pub fn extract_json(_env: &mut Environ, args: Vec<String>)
    -> Result<int, String>
{
    let mut filename = Path::new(".");
    let mut columns = Vec::new();
    {
        let mut ap = ArgumentParser::new();
        ap.refer(&mut filename)
            .add_argument("filename", box Store::<Path>,
                "A JSON file to parse")
            .required();
        ap.refer(&mut columns)
            .add_argument("column", box List::<String>,
                "A columns to extract");
        match ap.parse(args, &mut stdout(), &mut stderr()) {
            Ok(()) => {}
            Err(0) => return Ok(0),
            Err(_) => return Ok(122),
        }
    }
    let mut file = try!(File::open(&filename)
        .map_err(|e| format!("Can't open file {}: {}",
                             filename.display(), e)));
    let json = try!(from_reader(&mut file)
        .map_err(|e| format!("Can't parse {}: {}", filename.display(), e)));
    let lst = match json {
        J::List(lst) => lst,
        _ => return Err(format!("Root entitity is not a list")),
    };
    let mut out = stdout();
    let ncols = columns.len();
    for obj in lst.iter() {
        let tree = match obj {
            &J::Object(ref tmap) => tmap,
            _ => return Err(format!("Not an object in a list")),
        };
        for (idx, col) in columns.iter().enumerate() {
            match tree.find(col) {
                Some(&J::String(ref x)) => try!(out.write_str(x.as_slice())
                    .map_err(|e| format!("Error writing to stdout: {}", e))),
                _ => {},
            };
            if idx < ncols - 1 {
                try!(out.write_char('\t')
                    .map_err(|e| format!("Error writing to stdout: {}", e)));
            }
        }
        try!(out.write_char('\n')
            .map_err(|e| format!("Error writing to stdout: {}", e)));
    }
    return Ok(0);
}
<|endoftext|>


<commit_before>

use error;

use serde;
use std::io;
use toml;
use value;

pub struct TomlSource(Option<toml::Table>);
pub struct TomlSink<W: io::Write>(W);

#[inline]
pub fn source<R>(mut r: R) -> error::Result<TomlSource>
    where R: io::Read
{
    let mut string = String::new();
    try!(r.read_to_string(&mut string));
    let mut parser = toml::Parser::new(&string);
    let table = parser.parse();
    let table = match table {
        Some(t) => t,
        None => {
            return Err(parser.errors.remove(0).into());
        },
    };
    Ok(TomlSource(Some(table)))
}

#[inline]
pub fn sink<W>(w: W) -> TomlSink<W>
    where W: io::Write
{
    TomlSink(w)
}

impl value::Source for TomlSource {
    #[inline]
    fn read(&mut self) -> error::Result<Option<value::Value>> {
        match self.0.take() {
            Some(v) => {
                let mut de = toml::Decoder::new(toml::Value::Table(v));
                match serde::Deserialize::deserialize(&mut de) {
                    Ok(v) => Ok(Some(v)),
                    Err(e) => Err(error::Error::from(e)),
                }
            },
            None => Ok(None),
        }
    }
}

impl<W> value::Sink for TomlSink<W>
    where W: io::Write
{
    #[inline]
    fn write(&mut self, value: value::Value) -> error::Result<()> {
        let mut e = toml::Encoder::new();
        try!(serde::Serialize::serialize(&value, &mut e));
        try!(write!(self.0, "{}", toml::Value::Table(e.toml).to_string()));
        try!(self.0.write(b"\n"));
        Ok(())
    }
}
<commit_msg>Improve error messages (#135)<commit_after>

use error;

use serde;
use std::io;
use std::panic;
use toml;
use value;

pub struct TomlSource(Option<toml::Table>);
pub struct TomlSink<W: io::Write>(W);

#[inline]
pub fn source<R>(mut r: R) -> error::Result<TomlSource>
    where R: io::Read
{
    let mut string = String::new();
    try!(r.read_to_string(&mut string));
    let mut parser = toml::Parser::new(&string);
    let table = parser.parse();
    let table = match table {
        Some(t) => t,
        None => {
            return Err(parser.errors.remove(0).into());
        },
    };
    Ok(TomlSource(Some(table)))
}

#[inline]
pub fn sink<W>(w: W) -> TomlSink<W>
    where W: io::Write
{
    TomlSink(w)
}

impl value::Source for TomlSource {
    #[inline]
    fn read(&mut self) -> error::Result<Option<value::Value>> {
        match self.0.take() {
            Some(v) => {
                let mut de = toml::Decoder::new(toml::Value::Table(v));
                match serde::Deserialize::deserialize(&mut de) {
                    Ok(v) => Ok(Some(v)),
                    Err(e) => Err(error::Error::from(e)),
                }
            },
            None => Ok(None),
        }
    }
}

impl<W> value::Sink for TomlSink<W>
    where W: io::Write
{
    #[inline]
    fn write(&mut self, value: value::Value) -> error::Result<()> {
        let mut e = toml::Encoder::new();
        match serde::Serialize::serialize(&value, &mut e) {
            Ok(()) => (),
            Err(toml::Error::NeedsKey) =>
                return Err("TOML document needs to have a table at the root".into()),
            Err(e) =>
                return Err(e.into()),
        }

        match panic::catch_unwind(move || toml::Value::Table(e.toml).to_string()) {
            Ok(s) => try!(self.0.write_all(s.as_bytes())),
            Err(cause) => {
                if let Some(s) = cause.downcast_ref::<&str>() {
                    if *s == "non-heterogeneous toml array" {
                        return Err("All elements in a TOML array need to be the same type".into());
                    }
                }

                // rethrow otherwise
                panic::resume_unwind(cause);
            }
        }

        try!(self.0.write_all(b"\n"));
        Ok(())
    }
}
<|endoftext|>


<commit_before>use rocksdb;
use kite::schema::FieldRef;
use byteorder::{ByteOrder, BigEndian};

use RocksDBIndexReader;
use key_builder::KeyBuilder;
use doc_id_set::DocIdSet;
use term_dictionary::TermRef;
use document_index::DocRef;

#[derive(Debug)]
pub enum SegmentReadError {
    RocksDB(rocksdb::Error),
}

pub trait Segment {
    fn load_statistic(&self, stat_name: &[u8]) -> Result<Option<i64>, SegmentReadError>;
    fn load_stored_field_value_raw(&self, doc_ord: u16, field_ref: FieldRef, value_type: &[u8]) -> Result<Option<Vec<u8>>, SegmentReadError>;
    fn load_term_directory(&self, field_ref: FieldRef, term_ref: TermRef) -> Result<Option<DocIdSet>, SegmentReadError>;
    fn load_deletion_list(&self) -> Result<Option<DocIdSet>, SegmentReadError>;
    fn id(&self) -> u32;

    fn doc_ref(&self, ord: u16) -> DocRef {
        DocRef::from_segment_ord(self.id(), ord)
    }
}

pub struct RocksDBSegment<'a> {
    reader: &'a RocksDBIndexReader<'a>,
    id: u32,
}

impl<'a> RocksDBSegment<'a> {
    pub fn new(reader: &'a RocksDBIndexReader, id: u32) -> RocksDBSegment<'a> {
        RocksDBSegment {
            reader: reader,
            id: id,
        }
    }
}

impl<'a> Segment for RocksDBSegment<'a> {
    fn id(&self) -> u32 {
        self.id
    }

    fn load_statistic(&self, stat_name: &[u8]) -> Result<Option<i64>, SegmentReadError> {
        let kb = KeyBuilder::segment_stat(self.id, stat_name);
        let val = try!(self.reader.snapshot.get(&kb.key())).map(|val| BigEndian::read_i64(&val));
        Ok(val)
    }

    fn load_stored_field_value_raw(&self, doc_ord: u16, field_ref: FieldRef, value_type: &[u8]) -> Result<Option<Vec<u8>>, SegmentReadError> {
        let kb = KeyBuilder::stored_field_value(self.id, doc_ord, field_ref.ord(), value_type);
        let val = try!(self.reader.snapshot.get(&kb.key()));
        Ok(val.map(|v| v.to_vec()))
    }

    fn load_term_directory(&self, field_ref: FieldRef, term_ref: TermRef) -> Result<Option<DocIdSet>, SegmentReadError> {
        let kb = KeyBuilder::segment_dir_list(self.id, field_ref.ord(), term_ref.ord());
        let doc_id_set = try!(self.reader.snapshot.get(&kb.key())).map(|doc_id_set| DocIdSet::FromRDB(doc_id_set));
        Ok(doc_id_set)
    }

    fn load_deletion_list(&self) -> Result<Option<DocIdSet>, SegmentReadError> {
        let kb = KeyBuilder::segment_del_list(self.id);
        let doc_id_set = try!(self.reader.snapshot.get(&kb.key())).map(|doc_id_set| DocIdSet::FromRDB(doc_id_set));
        Ok(doc_id_set)
    }
}

impl From<rocksdb::Error> for SegmentReadError {
    fn from(e: rocksdb::Error) -> SegmentReadError {
        SegmentReadError::RocksDB(e)
    }
}
<commit_msg>Add conversion from SegmentReadError into String<commit_after>use rocksdb;
use kite::schema::FieldRef;
use byteorder::{ByteOrder, BigEndian};

use RocksDBIndexReader;
use key_builder::KeyBuilder;
use doc_id_set::DocIdSet;
use term_dictionary::TermRef;
use document_index::DocRef;

#[derive(Debug)]
pub enum SegmentReadError {
    RocksDB(rocksdb::Error),
}

impl From<SegmentReadError> for String {
    fn from(e: SegmentReadError) -> String {
        match e {
            SegmentReadError::RocksDB(e) => e.into(),
        }
    }
}

pub trait Segment {
    fn load_statistic(&self, stat_name: &[u8]) -> Result<Option<i64>, SegmentReadError>;
    fn load_stored_field_value_raw(&self, doc_ord: u16, field_ref: FieldRef, value_type: &[u8]) -> Result<Option<Vec<u8>>, SegmentReadError>;
    fn load_term_directory(&self, field_ref: FieldRef, term_ref: TermRef) -> Result<Option<DocIdSet>, SegmentReadError>;
    fn load_deletion_list(&self) -> Result<Option<DocIdSet>, SegmentReadError>;
    fn id(&self) -> u32;

    fn doc_ref(&self, ord: u16) -> DocRef {
        DocRef::from_segment_ord(self.id(), ord)
    }
}

pub struct RocksDBSegment<'a> {
    reader: &'a RocksDBIndexReader<'a>,
    id: u32,
}

impl<'a> RocksDBSegment<'a> {
    pub fn new(reader: &'a RocksDBIndexReader, id: u32) -> RocksDBSegment<'a> {
        RocksDBSegment {
            reader: reader,
            id: id,
        }
    }
}

impl<'a> Segment for RocksDBSegment<'a> {
    fn id(&self) -> u32 {
        self.id
    }

    fn load_statistic(&self, stat_name: &[u8]) -> Result<Option<i64>, SegmentReadError> {
        let kb = KeyBuilder::segment_stat(self.id, stat_name);
        let val = try!(self.reader.snapshot.get(&kb.key())).map(|val| BigEndian::read_i64(&val));
        Ok(val)
    }

    fn load_stored_field_value_raw(&self, doc_ord: u16, field_ref: FieldRef, value_type: &[u8]) -> Result<Option<Vec<u8>>, SegmentReadError> {
        let kb = KeyBuilder::stored_field_value(self.id, doc_ord, field_ref.ord(), value_type);
        let val = try!(self.reader.snapshot.get(&kb.key()));
        Ok(val.map(|v| v.to_vec()))
    }

    fn load_term_directory(&self, field_ref: FieldRef, term_ref: TermRef) -> Result<Option<DocIdSet>, SegmentReadError> {
        let kb = KeyBuilder::segment_dir_list(self.id, field_ref.ord(), term_ref.ord());
        let doc_id_set = try!(self.reader.snapshot.get(&kb.key())).map(|doc_id_set| DocIdSet::FromRDB(doc_id_set));
        Ok(doc_id_set)
    }

    fn load_deletion_list(&self) -> Result<Option<DocIdSet>, SegmentReadError> {
        let kb = KeyBuilder::segment_del_list(self.id);
        let doc_id_set = try!(self.reader.snapshot.get(&kb.key())).map(|doc_id_set| DocIdSet::FromRDB(doc_id_set));
        Ok(doc_id_set)
    }
}

impl From<rocksdb::Error> for SegmentReadError {
    fn from(e: rocksdb::Error) -> SegmentReadError {
        SegmentReadError::RocksDB(e)
    }
}
<|endoftext|>


<commit_before>extern crate grin_api as api;
extern crate grin_util as util;
extern crate hyper;

use api::*;
use hyper::{Body, Request};
use std::net::SocketAddr;
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use std::sync::Arc;
use std::{thread, time};

struct IndexHandler {
	list: Vec<String>,
}

impl IndexHandler {}

impl Handler for IndexHandler {
	fn get(&self, _req: Request<Body>) -> ResponseFuture {
		json_response_pretty(&self.list)
	}
}

pub struct CounterMiddleware {
	counter: AtomicUsize,
}

impl CounterMiddleware {
	fn new() -> CounterMiddleware {
		CounterMiddleware {
			counter: ATOMIC_USIZE_INIT,
		}
	}

	fn value(&self) -> usize {
		self.counter.load(Ordering::SeqCst)
	}
}

impl Handler for CounterMiddleware {
	fn call(
		&self,
		req: Request<Body>,
		mut handlers: Box<Iterator<Item = HandlerObj>>,
	) -> ResponseFuture {
		self.counter.fetch_add(1, Ordering::SeqCst);
		handlers.next().unwrap().call(req, handlers)
	}
}

fn build_router() -> Router {
	let route_list = vec!["get blocks".to_string(), "get chain".to_string()];
	let index_handler = IndexHandler { list: route_list };
	let mut router = Router::new();
	router
		.add_route("/v1/*", Arc::new(index_handler))
		.expect("add_route failed")
		.add_middleware(Arc::new(LoggingMiddleware {}));
	router
}

#[test]
fn test_start_api() {
	util::init_test_logger();
	let mut server = ApiServer::new();
	let mut router = build_router();
	let counter = Arc::new(CounterMiddleware::new());
	// add middleware to the root
	router.add_middleware(counter.clone());
	let server_addr = "127.0.0.1:14434";
	let addr: SocketAddr = server_addr.parse().expect("unable to parse server address");
	assert!(server.start(addr, router, None).is_ok());
	let url = format!("http://{}/v1/", server_addr);
	let index = request_with_retry(url.as_str()).unwrap();
	assert_eq!(index.len(), 2);
	assert_eq!(counter.value(), 1);
	assert!(server.stop());
	thread::sleep(time::Duration::from_millis(1_000));
}

// To enable this test you need a trusted PKCS12 (p12) certificate bundle
// Hyper-tls client doesn't accept self-signed certificates. The easiest way is to use mkcert
// https://github.com/FiloSottile/mkcert to install CA and generate a certificate on your local machine.
// You need to put the file to api/tests folder
#[ignore]
#[test]
fn test_start_api_tls() {
	util::init_test_logger();
	let tls_conf = TLSConfig::new(
		"tests/fullchain.pem".to_string(),
		"tests/privkey.pem".to_string(),
	);
	let mut server = ApiServer::new();
	let router = build_router();
	let server_addr = "0.0.0.0:14444";
	let addr: SocketAddr = server_addr.parse().expect("unable to parse server address");
	assert!(server.start(addr, router, Some(tls_conf)).is_ok());
	let index = request_with_retry("https://yourdomain.com:14444/v1/").unwrap();
	assert_eq!(index.len(), 2);
	assert!(!server.stop());
}

fn request_with_retry(url: &str) -> Result<Vec<String>, api::Error> {
	let mut tries = 0;
	loop {
		let res = api::client::get::<Vec<String>>(url, None);
		if res.is_ok() {
			return res;
		}
		if tries > 5 {
			return res;
		}
		tries += 1;
	}
}
<commit_msg>Add sleep before retry<commit_after>extern crate grin_api as api;
extern crate grin_util as util;
extern crate hyper;

use api::*;
use hyper::{Body, Request};
use std::net::SocketAddr;
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use std::sync::Arc;
use std::{thread, time};

struct IndexHandler {
	list: Vec<String>,
}

impl IndexHandler {}

impl Handler for IndexHandler {
	fn get(&self, _req: Request<Body>) -> ResponseFuture {
		json_response_pretty(&self.list)
	}
}

pub struct CounterMiddleware {
	counter: AtomicUsize,
}

impl CounterMiddleware {
	fn new() -> CounterMiddleware {
		CounterMiddleware {
			counter: ATOMIC_USIZE_INIT,
		}
	}

	fn value(&self) -> usize {
		self.counter.load(Ordering::SeqCst)
	}
}

impl Handler for CounterMiddleware {
	fn call(
		&self,
		req: Request<Body>,
		mut handlers: Box<Iterator<Item = HandlerObj>>,
	) -> ResponseFuture {
		self.counter.fetch_add(1, Ordering::SeqCst);
		handlers.next().unwrap().call(req, handlers)
	}
}

fn build_router() -> Router {
	let route_list = vec!["get blocks".to_string(), "get chain".to_string()];
	let index_handler = IndexHandler { list: route_list };
	let mut router = Router::new();
	router
		.add_route("/v1/*", Arc::new(index_handler))
		.expect("add_route failed")
		.add_middleware(Arc::new(LoggingMiddleware {}));
	router
}

#[test]
fn test_start_api() {
	util::init_test_logger();
	let mut server = ApiServer::new();
	let mut router = build_router();
	let counter = Arc::new(CounterMiddleware::new());
	// add middleware to the root
	router.add_middleware(counter.clone());
	let server_addr = "127.0.0.1:14434";
	let addr: SocketAddr = server_addr.parse().expect("unable to parse server address");
	assert!(server.start(addr, router, None).is_ok());
	let url = format!("http://{}/v1/", server_addr);
	let index = request_with_retry(url.as_str()).unwrap();
	assert_eq!(index.len(), 2);
	assert_eq!(counter.value(), 1);
	assert!(server.stop());
	thread::sleep(time::Duration::from_millis(1_000));
}

// To enable this test you need a trusted PKCS12 (p12) certificate bundle
// Hyper-tls client doesn't accept self-signed certificates. The easiest way is to use mkcert
// https://github.com/FiloSottile/mkcert to install CA and generate a certificate on your local machine.
// You need to put the file to api/tests folder
#[ignore]
#[test]
fn test_start_api_tls() {
	util::init_test_logger();
	let tls_conf = TLSConfig::new(
		"tests/fullchain.pem".to_string(),
		"tests/privkey.pem".to_string(),
	);
	let mut server = ApiServer::new();
	let router = build_router();
	let server_addr = "0.0.0.0:14444";
	let addr: SocketAddr = server_addr.parse().expect("unable to parse server address");
	assert!(server.start(addr, router, Some(tls_conf)).is_ok());
	let index = request_with_retry("https://yourdomain.com:14444/v1/").unwrap();
	assert_eq!(index.len(), 2);
	assert!(!server.stop());
}

fn request_with_retry(url: &str) -> Result<Vec<String>, api::Error> {
	let mut tries = 0;
	loop {
		let res = api::client::get::<Vec<String>>(url, None);
		if res.is_ok() {
			return res;
		}
		if tries > 5 {
			return res;
		}
		tries += 1;
		thread::sleep(time::Duration::from_millis(500));
	}
}
<|endoftext|>


<commit_before>//! Contains high-level interface for an events-based XML emitter.
//!
//! The most important type in this module is `EventWriter` which allows writing an XML document
//! to some output stream.

pub use self::emitter::Result;
pub use self::emitter::EmitterError as Error;
pub use self::config::EmitterConfig;
pub use self::events::XmlEvent;

use self::emitter::Emitter;

use std::io::prelude::*;

mod emitter;
mod config;
pub mod events;

/// A wrapper around an `std::io::Write` instance which emits XML document according to provided
/// events.
pub struct EventWriter<W> {
    sink: W,
    emitter: Emitter
}

impl<W: Write> EventWriter<W> {
    /// Creates a new `EventWriter` out of an `std::io::Write` instance using the default
    /// configuration.
    #[inline]
    pub fn new(sink: W) -> EventWriter<W> {
        EventWriter::new_with_config(sink, EmitterConfig::new())
    }

    /// Creates a new `EventWriter` out of an `std::io::Write` instance using the provided
    /// configuration.
    #[inline]
    pub fn new_with_config(sink: W, config: EmitterConfig) -> EventWriter<W> {
        EventWriter {
            sink: sink,
            emitter: Emitter::new(config)
        }
    }

    /// Writes the next piece of XML document according to the provided event.
    ///
    /// Note that output data may not exactly correspond to the written event because
    /// of various configuration options. For example, `XmlEvent::EndElement` may
    /// correspond to a separate closing element or it may cause writing an empty element.
    /// Another example is that `XmlEvent::CData` may be represented as characters in
    /// the output stream.
    pub fn write<'a, E>(&mut self, event: E) -> Result<()> where E: Into<XmlEvent<'a>> {
        match event.into() {
            XmlEvent::StartDocument { version, encoding, standalone } =>
                self.emitter.emit_start_document(&mut self.sink, version, encoding.unwrap_or("UTF-8"), standalone),
            XmlEvent::ProcessingInstruction { name, data } =>
                self.emitter.emit_processing_instruction(&mut self.sink, name, data),
            XmlEvent::StartElement { name, attributes, namespace } => {
                self.emitter.namespace_stack_mut().push_empty().checked_target().extend(namespace.as_ref());
                self.emitter.emit_start_element(&mut self.sink, name, &attributes)
            }
            XmlEvent::EndElement { name } => {
                let r = self.emitter.emit_end_element(&mut self.sink, name);
                self.emitter.namespace_stack_mut().try_pop();
                r
            }
            XmlEvent::Comment(content) =>
                self.emitter.emit_comment(&mut self.sink, content),
            XmlEvent::CData(content) =>
                self.emitter.emit_cdata(&mut self.sink, content),
            XmlEvent::Characters(content) =>
                self.emitter.emit_characters(&mut self.sink, content)
        }
    }

    /// Unwraps this `EventWriter`, returning the underlying writer.
    ///
    /// Note that this is a destructive operation: unwrapping a writer and then wrapping
    /// it again with `EventWriter::new()` will create a fresh writer whose state will be
    /// blank; for example, accumulated namespaces will be reset.
    pub fn into_inner(self) -> W {
        self.sink
    }
}
<commit_msg>Added `XmlWriter::inner_mut()`<commit_after>//! Contains high-level interface for an events-based XML emitter.
//!
//! The most important type in this module is `EventWriter` which allows writing an XML document
//! to some output stream.

pub use self::emitter::Result;
pub use self::emitter::EmitterError as Error;
pub use self::config::EmitterConfig;
pub use self::events::XmlEvent;

use self::emitter::Emitter;

use std::io::prelude::*;

mod emitter;
mod config;
pub mod events;

/// A wrapper around an `std::io::Write` instance which emits XML document according to provided
/// events.
pub struct EventWriter<W> {
    sink: W,
    emitter: Emitter
}

impl<W: Write> EventWriter<W> {
    /// Creates a new `EventWriter` out of an `std::io::Write` instance using the default
    /// configuration.
    #[inline]
    pub fn new(sink: W) -> EventWriter<W> {
        EventWriter::new_with_config(sink, EmitterConfig::new())
    }

    /// Creates a new `EventWriter` out of an `std::io::Write` instance using the provided
    /// configuration.
    #[inline]
    pub fn new_with_config(sink: W, config: EmitterConfig) -> EventWriter<W> {
        EventWriter {
            sink,
            emitter: Emitter::new(config)
        }
    }

    /// Writes the next piece of XML document according to the provided event.
    ///
    /// Note that output data may not exactly correspond to the written event because
    /// of various configuration options. For example, `XmlEvent::EndElement` may
    /// correspond to a separate closing element or it may cause writing an empty element.
    /// Another example is that `XmlEvent::CData` may be represented as characters in
    /// the output stream.
    pub fn write<'a, E>(&mut self, event: E) -> Result<()> where E: Into<XmlEvent<'a>> {
        match event.into() {
            XmlEvent::StartDocument { version, encoding, standalone } =>
                self.emitter.emit_start_document(&mut self.sink, version, encoding.unwrap_or("UTF-8"), standalone),
            XmlEvent::ProcessingInstruction { name, data } =>
                self.emitter.emit_processing_instruction(&mut self.sink, name, data),
            XmlEvent::StartElement { name, attributes, namespace } => {
                self.emitter.namespace_stack_mut().push_empty().checked_target().extend(namespace.as_ref());
                self.emitter.emit_start_element(&mut self.sink, name, &attributes)
            }
            XmlEvent::EndElement { name } => {
                let r = self.emitter.emit_end_element(&mut self.sink, name);
                self.emitter.namespace_stack_mut().try_pop();
                r
            }
            XmlEvent::Comment(content) =>
                self.emitter.emit_comment(&mut self.sink, content),
            XmlEvent::CData(content) =>
                self.emitter.emit_cdata(&mut self.sink, content),
            XmlEvent::Characters(content) =>
                self.emitter.emit_characters(&mut self.sink, content)
        }
    }

    /// Returns a mutable reference to the underlying `Writer`.
    ///
    /// Note that having a reference to the underlying sink makes it very easy to emit invalid XML
    /// documents. Use this method with care. Valid use cases for this method include accessing
    /// methods like `Write::flush`, which do not emit new data but rather change the state
    /// of the stream itself.
    pub fn inner_mut(&mut self) -> &mut W {
        &mut self.sink
    }

    /// Unwraps this `EventWriter`, returning the underlying writer.
    ///
    /// Note that this is a destructive operation: unwrapping a writer and then wrapping
    /// it again with `EventWriter::new()` will create a fresh writer whose state will be
    /// blank; for example, accumulated namespaces will be reset.
    pub fn into_inner(self) -> W {
        self.sink
    }
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::{ReadStream, Stream, StreamProducer};
use flac::metadata;
use flac::metadata::{SeekPoint, VorbisComment};

use std::env;
use std::io;
use std::io::Write;
use std::fs::File;

const USAGE: &'static str = "
Usage: metadata streaminfo [options] <filename>
       metadata comments [options] <filename>
       metadata seektable <filename>
       metadata --help

Options:
  --block-size       Show both the max and min block size from StreamInfo.
  --frame-size       Show both the max and min frame size from StreamInfo.
  --sample-rate      Show the sample rate from StreamInfo.
  --channels         Show the number of channels from StreamInfo.
  --bits-per-sample  Show the size in bits for each sample from StreamInfo.
  --total-samples    Show total number of samples from StreamInfo.
  --md5              Show the MD5 signature from StreamInfo.
  --vendor           Show the vendor string from VorbisComment.
  --name=NAME        Show the comments matching the `NAME` from VorbisComment.
  --export=FILE      Export VorbisComment to file.
  -h, --help         Show this message.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_filename: String,
  cmd_streaminfo: bool,
  cmd_comments: bool,
  cmd_seektable: bool,
  flag_block_size: bool,
  flag_frame_size: bool,
  flag_sample_rate: bool,
  flag_channels: bool,
  flag_bits_per_sample: bool,
  flag_total_samples: bool,
  flag_md5: bool,
  flag_vendor: bool,
  flag_name: Option<String>,
  flag_export: Option<String>,
}

macro_rules! format_print (
  ($format_str: expr, $opt_str: expr, $data: expr, $no_flag: expr) => (
    {
      println!($format_str, if $no_flag {
        $opt_str
      } else {
        ""
      }, $data);
    }
  );
);

fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
 where P: StreamProducer {
  let info     = stream.info();
  let no_flags = (args.flag_block_size      || args.flag_frame_size    ||
                  args.flag_sample_rate     || args.flag_channels      ||
                  args.flag_bits_per_sample || args.flag_total_samples ||
                  args.flag_md5) == false;

  if no_flags || args.flag_block_size {
    println!("Minimum block size: {} samples", info.min_block_size);
    println!("Maximum block size: {} samples", info.max_block_size);
  }

  if no_flags || args.flag_frame_size {
    println!("Minimum frame size: {} bytes", info.min_frame_size);
    println!("Maximum frame size: {} bytes", info.max_frame_size);
  }

  if no_flags || args.flag_sample_rate {
    format_print!("{}{} Hz", "Sample rate: ", info.sample_rate, no_flags);
  }

  if no_flags || args.flag_channels {
    format_print!("{}{}", "Number of channels: ", info.channels, no_flags);
  }

  if no_flags || args.flag_bits_per_sample {
    format_print!("{}{}", "Bits per samples: ", info.bits_per_sample,
                                                no_flags);
  }

  if no_flags || args.flag_total_samples {
    format_print!("{}{}", "Total samples: ", info.total_samples, no_flags);
  }

  if no_flags || args.flag_md5 {
    let mut md5  = String::with_capacity(32);

    for byte in &info.md5_sum {
      let hex = format!("{:02x}", byte);

      md5.push_str(&hex);
    }

    format_print!("{}{}", "MD5 sum: ", md5, no_flags);
  }
}

fn print_vorbis_comments(vorbis_comment: &VorbisComment, args: &Arguments) {
  let no_flags  = (args.flag_vendor || args.flag_name.is_some()) == false;

  if no_flags || args.flag_vendor {
    format_print!("{}{}", "Vendor string: ", vorbis_comment.vendor_string,
                                             no_flags);
  }

  if no_flags {
    let mut index = 1;

    println!("Number of Comments: {}", vorbis_comment.comments.len());

    for (name, value) in &vorbis_comment.comments {
      println!("  {}: \"{}\" = {}", index, name, value);

      index += 1;
    }
  } else {
    if let Some(ref name) = args.flag_name {
      vorbis_comment.comments.get(name)
                             .map(|value| println!("{}", value));
    }
  }
}

fn export_vorbis_comments(vorbis_comment: &VorbisComment, filename: &str)
                          -> io::Result<()> {
  let mut file  = try!(File::create(filename));

  for (name, value) in &vorbis_comment.comments {
    try!(write!(file, "{}={}\n", name, value));
  }

  Ok(())
}

fn print_seek_table(seek_points: &[SeekPoint]) {
  let mut count = 0;

  println!("Number of Seek Points: {}", seek_points.len());

  for seek_point in seek_points {
    println!("Seek Point #{}", count);
    println!("  Sample number: {}", seek_point.sample_number);
    println!("  Stream offset: {}", seek_point.stream_offset);
    println!("  Frame samples: {}", seek_point.frame_samples);
    count += 1;
  }
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.argv(env::args()).decode())
    .unwrap_or_else(|e| e.exit());

  let stream = Stream::<ReadStream<File>>::from_file(&args.arg_filename)
                 .expect("Couldn't parse file");

  if args.cmd_streaminfo {
    print_stream_info(&stream, &args);
  }

  for meta in stream.metadata() {
    match meta.data {
      metadata::Data::VorbisComment(ref v) => {
        if args.cmd_comments {
          if let Some(ref filename) = args.flag_export {
            export_vorbis_comments(v, filename)
              .expect("couldn't write to file")
          } else {
            print_vorbis_comments(v, &args)
          }
        }
      }
      metadata::Data::SeekTable(ref s)     => {
        if args.cmd_seektable {
          print_seek_table(s);
        }
      }
      _                                    => continue,
    }
  }
}
<commit_msg>Export self in metadata example<commit_after>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::{ReadStream, Stream, StreamProducer};
use flac::metadata::{self, SeekPoint, VorbisComment};

use std::env;
use std::io::{self, Write};
use std::fs::File;

const USAGE: &'static str = "
Usage: metadata streaminfo [options] <filename>
       metadata comments [options] <filename>
       metadata seektable <filename>
       metadata --help

Options:
  --block-size       Show both the max and min block size from StreamInfo.
  --frame-size       Show both the max and min frame size from StreamInfo.
  --sample-rate      Show the sample rate from StreamInfo.
  --channels         Show the number of channels from StreamInfo.
  --bits-per-sample  Show the size in bits for each sample from StreamInfo.
  --total-samples    Show total number of samples from StreamInfo.
  --md5              Show the MD5 signature from StreamInfo.
  --vendor           Show the vendor string from VorbisComment.
  --name=NAME        Show the comments matching the `NAME` from VorbisComment.
  --export=FILE      Export VorbisComment to file.
  -h, --help         Show this message.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_filename: String,
  cmd_streaminfo: bool,
  cmd_comments: bool,
  cmd_seektable: bool,
  flag_block_size: bool,
  flag_frame_size: bool,
  flag_sample_rate: bool,
  flag_channels: bool,
  flag_bits_per_sample: bool,
  flag_total_samples: bool,
  flag_md5: bool,
  flag_vendor: bool,
  flag_name: Option<String>,
  flag_export: Option<String>,
}

macro_rules! format_print (
  ($format_str: expr, $opt_str: expr, $data: expr, $no_flag: expr) => (
    {
      println!($format_str, if $no_flag {
        $opt_str
      } else {
        ""
      }, $data);
    }
  );
);

fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
 where P: StreamProducer {
  let info     = stream.info();
  let no_flags = (args.flag_block_size      || args.flag_frame_size    ||
                  args.flag_sample_rate     || args.flag_channels      ||
                  args.flag_bits_per_sample || args.flag_total_samples ||
                  args.flag_md5) == false;

  if no_flags || args.flag_block_size {
    println!("Minimum block size: {} samples", info.min_block_size);
    println!("Maximum block size: {} samples", info.max_block_size);
  }

  if no_flags || args.flag_frame_size {
    println!("Minimum frame size: {} bytes", info.min_frame_size);
    println!("Maximum frame size: {} bytes", info.max_frame_size);
  }

  if no_flags || args.flag_sample_rate {
    format_print!("{}{} Hz", "Sample rate: ", info.sample_rate, no_flags);
  }

  if no_flags || args.flag_channels {
    format_print!("{}{}", "Number of channels: ", info.channels, no_flags);
  }

  if no_flags || args.flag_bits_per_sample {
    format_print!("{}{}", "Bits per samples: ", info.bits_per_sample,
                                                no_flags);
  }

  if no_flags || args.flag_total_samples {
    format_print!("{}{}", "Total samples: ", info.total_samples, no_flags);
  }

  if no_flags || args.flag_md5 {
    let mut md5  = String::with_capacity(32);

    for byte in &info.md5_sum {
      let hex = format!("{:02x}", byte);

      md5.push_str(&hex);
    }

    format_print!("{}{}", "MD5 sum: ", md5, no_flags);
  }
}

fn print_vorbis_comments(vorbis_comment: &VorbisComment, args: &Arguments) {
  let no_flags  = (args.flag_vendor || args.flag_name.is_some()) == false;

  if no_flags || args.flag_vendor {
    format_print!("{}{}", "Vendor string: ", vorbis_comment.vendor_string,
                                             no_flags);
  }

  if no_flags {
    let mut index = 1;

    println!("Number of Comments: {}", vorbis_comment.comments.len());

    for (name, value) in &vorbis_comment.comments {
      println!("  {}: \"{}\" = {}", index, name, value);

      index += 1;
    }
  } else {
    if let Some(ref name) = args.flag_name {
      vorbis_comment.comments.get(name)
                             .map(|value| println!("{}", value));
    }
  }
}

fn export_vorbis_comments(vorbis_comment: &VorbisComment, filename: &str)
                          -> io::Result<()> {
  let mut file  = try!(File::create(filename));

  for (name, value) in &vorbis_comment.comments {
    try!(write!(file, "{}={}\n", name, value));
  }

  Ok(())
}

fn print_seek_table(seek_points: &[SeekPoint]) {
  let mut count = 0;

  println!("Number of Seek Points: {}", seek_points.len());

  for seek_point in seek_points {
    println!("Seek Point #{}", count);
    println!("  Sample number: {}", seek_point.sample_number);
    println!("  Stream offset: {}", seek_point.stream_offset);
    println!("  Frame samples: {}", seek_point.frame_samples);
    count += 1;
  }
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.argv(env::args()).decode())
    .unwrap_or_else(|e| e.exit());

  let stream = Stream::<ReadStream<File>>::from_file(&args.arg_filename)
                 .expect("Couldn't parse file");

  if args.cmd_streaminfo {
    print_stream_info(&stream, &args);
  }

  for meta in stream.metadata() {
    match meta.data {
      metadata::Data::VorbisComment(ref v) => {
        if args.cmd_comments {
          if let Some(ref filename) = args.flag_export {
            export_vorbis_comments(v, filename)
              .expect("couldn't write to file")
          } else {
            print_vorbis_comments(v, &args)
          }
        }
      }
      metadata::Data::SeekTable(ref s)     => {
        if args.cmd_seektable {
          print_seek_table(s);
        }
      }
      _                                    => continue,
    }
  }
}
<|endoftext|>


<commit_before>use ffi;
use ffi::{YamlEncoding, YamlSequenceStyle, YamlScalarStyle};
use std::cast;
use std::ptr;
use std::c_str::CString;
use std::c_vec::CVec;

pub struct InternalEvent {
    pub event_mem: ffi::yaml_event_t
}

impl Drop for InternalEvent {
    fn drop(&mut self) {
        unsafe {
            self.event_mem.delete()
        }
    }
}

#[deriving(Eq)]
#[deriving(Show)]
pub struct YamlVersionDirective {
    pub major: int,
    pub minor: int,
}

#[deriving(Eq)]
#[deriving(Show)]
pub struct YamlTagDirective {
    pub handle: ~[u8],
    pub prefix: ~[u8],
}

#[deriving(Eq)]
#[deriving(Show)]
pub struct YamlSequenceParam {
    anchor: Option<~[u8]>,
    tag: Option<~[u8]>,
    implicit: bool,
    style: YamlSequenceStyle
}

#[deriving(Eq)]
#[deriving(Show)]
pub struct YamlScalarParam {
    anchor: Option<~[u8]>,
    tag: Option<~[u8]>,
    value: ~[u8],
    plain_implicit: bool,
    quoted_implicit: bool,
    style: YamlScalarStyle
}

#[deriving(Eq)]
#[deriving(Show)]
pub enum YamlEvent {
    YamlNoEvent,
    YamlStreamStartEvent(YamlEncoding),
    YamlStreamEndEvent,
    YamlDocumentStartEvent(Option<YamlVersionDirective>, ~[YamlTagDirective], bool),
    YamlDocumentEndEvent(bool),
    YamlAliasEvent(~[u8]),
    YamlScalarEvent(YamlScalarParam),
    YamlSequenceStartEvent(YamlSequenceParam),
    YamlSequenceEndEvent,
    YamlMappingStartEvent(YamlSequenceParam),
    YamlMappingEndEvent,
}

fn c_str_into_owned_bytes(c_str: *ffi::yaml_char_t) -> Option<~[u8]> {
    unsafe {
        if c_str == ptr::null() {
            None
        } else {
            Some(CString::new(c_str as *i8, false).as_bytes_no_nul().into_owned())
        }
    }
}

impl YamlEvent {
    pub unsafe fn load(event: &InternalEvent) -> YamlEvent {
        match event.event_mem.event_type {
            ffi::YAML_NO_EVENT => YamlNoEvent,
            ffi::YAML_STREAM_START_EVENT => {
                let evt_data: &ffi::yaml_stream_start_event_t = cast::transmute(&event.event_mem.data);
                YamlStreamStartEvent(evt_data.encoding)
            },
            ffi::YAML_STREAM_END_EVENT => YamlStreamEndEvent,
            ffi::YAML_DOCUMENT_START_EVENT => {
                let evt_data: &ffi::yaml_document_start_event_t = cast::transmute(&event.event_mem.data);
                let vsn_dir = if evt_data.version_directive == ptr::null() {
                    None
                } else {
                    let c_vsn_dir: &ffi::yaml_version_directive_t = cast::transmute(evt_data.version_directive);
                    Some(YamlVersionDirective { major: c_vsn_dir.major as int, minor: c_vsn_dir.minor as int })
                };
                let mut tag_dirs = ~[];
                let mut tag_ptr = evt_data.tag_directives.start;
                while tag_ptr != ptr::null() && tag_ptr != evt_data.tag_directives.end {
                    let tag_ref: &ffi::yaml_tag_directive_t = cast::transmute(tag_ptr);
                    let handle = CString::new(tag_ref.handle, false).as_bytes_no_nul().into_owned();
                    let prefix = CString::new(tag_ref.prefix, false).as_bytes_no_nul().into_owned();
                    tag_dirs.push(YamlTagDirective { handle: handle, prefix: prefix });
                    tag_ptr = tag_ptr.offset(1);
                }
                let implicit = evt_data.implicit != 0;

                YamlDocumentStartEvent(vsn_dir, tag_dirs, implicit)
            },
            ffi::YAML_DOCUMENT_END_EVENT => {
                let evt_data: &ffi::yaml_document_end_event_t = cast::transmute(&event.event_mem.data);
                let implicit = evt_data.implicit != 0;

                YamlDocumentEndEvent(implicit)
            },
            ffi::YAML_ALIAS_EVENT => {
                let evt_data: &ffi::yaml_alias_event_t = cast::transmute(&event.event_mem.data);
                let anchor = CString::new(evt_data.anchor as *i8, false).as_bytes_no_nul().into_owned();

                YamlAliasEvent(anchor)
            },
            ffi::YAML_SCALAR_EVENT => {
                let evt_data: &ffi::yaml_scalar_event_t = cast::transmute(&event.event_mem.data);
                let value = CVec::new(evt_data.value as *mut u8, evt_data.length as uint).as_slice().into_owned();

                YamlScalarEvent(YamlScalarParam {
                    anchor: c_str_into_owned_bytes(evt_data.anchor),
                    tag: c_str_into_owned_bytes(evt_data.tag),
                    value: value,
                    plain_implicit: evt_data.plain_implicit != 0,
                    quoted_implicit: evt_data.quoted_implicit != 0,
                    style: evt_data.style
                })
            },
            ffi::YAML_SEQUENCE_START_EVENT => {
                let evt_data: &ffi::yaml_sequence_start_event_t = cast::transmute(&event.event_mem.data);

                YamlSequenceStartEvent(YamlSequenceParam {
                    anchor: c_str_into_owned_bytes(evt_data.anchor),
                    tag: c_str_into_owned_bytes(evt_data.tag),
                    implicit: evt_data.implicit != 0,
                    style: evt_data.style
                })
            },
            ffi::YAML_SEQUENCE_END_EVENT => YamlSequenceEndEvent,
            ffi::YAML_MAPPING_START_EVENT => {
                let evt_data: &ffi::yaml_mapping_start_event_t = cast::transmute(&event.event_mem.data);

                YamlMappingStartEvent(YamlSequenceParam {
                    anchor: c_str_into_owned_bytes(evt_data.anchor),
                    tag: c_str_into_owned_bytes(evt_data.tag),
                    implicit: evt_data.implicit != 0,
                    style: evt_data.style
                })
            },
            ffi::YAML_MAPPING_END_EVENT => YamlMappingEndEvent,
            _ => fail!("unknown event type")
        }
    }
}
<commit_msg>Remove unnecessary pub field<commit_after>use ffi;
use ffi::{YamlEncoding, YamlSequenceStyle, YamlScalarStyle};
use std::cast;
use std::ptr;
use std::c_str::CString;
use std::c_vec::CVec;

pub struct InternalEvent {
    event_mem: ffi::yaml_event_t
}

impl Drop for InternalEvent {
    fn drop(&mut self) {
        unsafe {
            self.event_mem.delete()
        }
    }
}

#[deriving(Eq)]
#[deriving(Show)]
pub struct YamlVersionDirective {
    pub major: int,
    pub minor: int,
}

#[deriving(Eq)]
#[deriving(Show)]
pub struct YamlTagDirective {
    pub handle: ~[u8],
    pub prefix: ~[u8],
}

#[deriving(Eq)]
#[deriving(Show)]
pub struct YamlSequenceParam {
    anchor: Option<~[u8]>,
    tag: Option<~[u8]>,
    implicit: bool,
    style: YamlSequenceStyle
}

#[deriving(Eq)]
#[deriving(Show)]
pub struct YamlScalarParam {
    anchor: Option<~[u8]>,
    tag: Option<~[u8]>,
    value: ~[u8],
    plain_implicit: bool,
    quoted_implicit: bool,
    style: YamlScalarStyle
}

#[deriving(Eq)]
#[deriving(Show)]
pub enum YamlEvent {
    YamlNoEvent,
    YamlStreamStartEvent(YamlEncoding),
    YamlStreamEndEvent,
    YamlDocumentStartEvent(Option<YamlVersionDirective>, ~[YamlTagDirective], bool),
    YamlDocumentEndEvent(bool),
    YamlAliasEvent(~[u8]),
    YamlScalarEvent(YamlScalarParam),
    YamlSequenceStartEvent(YamlSequenceParam),
    YamlSequenceEndEvent,
    YamlMappingStartEvent(YamlSequenceParam),
    YamlMappingEndEvent,
}

fn c_str_into_owned_bytes(c_str: *ffi::yaml_char_t) -> Option<~[u8]> {
    unsafe {
        if c_str == ptr::null() {
            None
        } else {
            Some(CString::new(c_str as *i8, false).as_bytes_no_nul().into_owned())
        }
    }
}

impl YamlEvent {
    pub unsafe fn load(event: &InternalEvent) -> YamlEvent {
        match event.event_mem.event_type {
            ffi::YAML_NO_EVENT => YamlNoEvent,
            ffi::YAML_STREAM_START_EVENT => {
                let evt_data: &ffi::yaml_stream_start_event_t = cast::transmute(&event.event_mem.data);
                YamlStreamStartEvent(evt_data.encoding)
            },
            ffi::YAML_STREAM_END_EVENT => YamlStreamEndEvent,
            ffi::YAML_DOCUMENT_START_EVENT => {
                let evt_data: &ffi::yaml_document_start_event_t = cast::transmute(&event.event_mem.data);
                let vsn_dir = if evt_data.version_directive == ptr::null() {
                    None
                } else {
                    let c_vsn_dir: &ffi::yaml_version_directive_t = cast::transmute(evt_data.version_directive);
                    Some(YamlVersionDirective { major: c_vsn_dir.major as int, minor: c_vsn_dir.minor as int })
                };
                let mut tag_dirs = ~[];
                let mut tag_ptr = evt_data.tag_directives.start;
                while tag_ptr != ptr::null() && tag_ptr != evt_data.tag_directives.end {
                    let tag_ref: &ffi::yaml_tag_directive_t = cast::transmute(tag_ptr);
                    let handle = CString::new(tag_ref.handle, false).as_bytes_no_nul().into_owned();
                    let prefix = CString::new(tag_ref.prefix, false).as_bytes_no_nul().into_owned();
                    tag_dirs.push(YamlTagDirective { handle: handle, prefix: prefix });
                    tag_ptr = tag_ptr.offset(1);
                }
                let implicit = evt_data.implicit != 0;

                YamlDocumentStartEvent(vsn_dir, tag_dirs, implicit)
            },
            ffi::YAML_DOCUMENT_END_EVENT => {
                let evt_data: &ffi::yaml_document_end_event_t = cast::transmute(&event.event_mem.data);
                let implicit = evt_data.implicit != 0;

                YamlDocumentEndEvent(implicit)
            },
            ffi::YAML_ALIAS_EVENT => {
                let evt_data: &ffi::yaml_alias_event_t = cast::transmute(&event.event_mem.data);
                let anchor = CString::new(evt_data.anchor as *i8, false).as_bytes_no_nul().into_owned();

                YamlAliasEvent(anchor)
            },
            ffi::YAML_SCALAR_EVENT => {
                let evt_data: &ffi::yaml_scalar_event_t = cast::transmute(&event.event_mem.data);
                let value = CVec::new(evt_data.value as *mut u8, evt_data.length as uint).as_slice().into_owned();

                YamlScalarEvent(YamlScalarParam {
                    anchor: c_str_into_owned_bytes(evt_data.anchor),
                    tag: c_str_into_owned_bytes(evt_data.tag),
                    value: value,
                    plain_implicit: evt_data.plain_implicit != 0,
                    quoted_implicit: evt_data.quoted_implicit != 0,
                    style: evt_data.style
                })
            },
            ffi::YAML_SEQUENCE_START_EVENT => {
                let evt_data: &ffi::yaml_sequence_start_event_t = cast::transmute(&event.event_mem.data);

                YamlSequenceStartEvent(YamlSequenceParam {
                    anchor: c_str_into_owned_bytes(evt_data.anchor),
                    tag: c_str_into_owned_bytes(evt_data.tag),
                    implicit: evt_data.implicit != 0,
                    style: evt_data.style
                })
            },
            ffi::YAML_SEQUENCE_END_EVENT => YamlSequenceEndEvent,
            ffi::YAML_MAPPING_START_EVENT => {
                let evt_data: &ffi::yaml_mapping_start_event_t = cast::transmute(&event.event_mem.data);

                YamlMappingStartEvent(YamlSequenceParam {
                    anchor: c_str_into_owned_bytes(evt_data.anchor),
                    tag: c_str_into_owned_bytes(evt_data.tag),
                    implicit: evt_data.implicit != 0,
                    style: evt_data.style
                })
            },
            ffi::YAML_MAPPING_END_EVENT => YamlMappingEndEvent,
            _ => fail!("unknown event type")
        }
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use std::ptr;
use libc::{c_void, size_t};
use libc::{PROT_READ, PROT_WRITE};
use libc::{MAP_PRIVATE, MAP_ANONYMOUS, MAP_GROWSDOWN, MAP_STACK};

fn mmap_stack(stack_size: size_t) -> *mut c_void {
    unsafe {
        let p = libc::mmap(ptr::null_mut(), stack_size, PROT_READ | PROT_WRITE,
                           MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN | MAP_STACK, -1, 0);
        assert!(p != libc::MAP_FAILED);
        p
    }

}

fn main() {
    println!("Hello, world!");

    let stack_size = 4 * 1024 * 1024;
    let child_stack = mmap_stack(stack_size);

    //TODO munmap child_stack
}
<commit_msg>cloning a child and letting it nicely panic<commit_after>extern crate libc;

use std::ptr;
use libc::{c_void, size_t, c_int};
use libc::{PROT_READ, PROT_WRITE};
use libc::{MAP_PRIVATE, MAP_ANONYMOUS, MAP_GROWSDOWN, MAP_STACK};
use libc::{CLONE_NEWUSER, CLONE_NEWNS, CLONE_NEWPID, SIGCHLD};

fn mmap_stack(stack_size: size_t) -> *mut c_void {
    unsafe {
        let p = libc::mmap(ptr::null_mut(), stack_size, PROT_READ | PROT_WRITE,
                           MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN | MAP_STACK, -1, 0);
        assert!(p != libc::MAP_FAILED);
        //TODO add guard pages
        p
    }

}

use std::thread;

extern "C" fn child_func(args: *mut c_void) -> c_int {
    println!("I'm called from child_func");
    // run everything in a new thread so exceptions bubble up to rust
    let h = thread::spawn(|| {
        panic!("Oops!");
    });

    match h.join() {
        Ok(_) => 0,
        Err(_) => 1,
    }
}

fn main() {
    println!("Hello, world!");

    let stack_size = 4 * 1024 * 1024;
    let child_stack = mmap_stack(stack_size);

    // stack grows down
    let child_stack_top = unsafe { child_stack.offset(stack_size as isize) };

    let child_pid = unsafe {
        libc::clone(child_func, child_stack_top, CLONE_NEWUSER|CLONE_NEWNS|CLONE_NEWPID|SIGCHLD, ptr::null_mut())
    };
    assert!(child_pid != -1);

    let mut child_status: c_int = 0;
    assert!(unsafe { libc::waitpid(child_pid, &mut child_status, 0) } != -1);
    println!("Child terminated: {}", child_status);

    //TODO munmap child_stack
}
<|endoftext|>


<commit_before>use mime::Mime;

header! {
    /// `Content-Type` header, defined in
    /// [RFC7231](http://tools.ietf.org/html/rfc7231#section-3.1.1.5)
    ///
    /// The `Content-Type` header field indicates the media type of the
    /// associated representation: either the representation enclosed in the
    /// message payload or the selected representation, as determined by the
    /// message semantics.  The indicated media type defines both the data
    /// format and how that data is intended to be processed by a recipient,
    /// within the scope of the received message semantics, after any content
    /// codings indicated by Content-Encoding are decoded.
    ///
    /// Although the `mime` crate allows the mime options to be any slice, this crate
    /// forces the use of Vec. This is to make sure the same header can't have more than 1 type. If
    /// this is an issue, it's possible to implement `Header` on a custom struct.
    ///
    /// # ABNF
    /// ```plain
    /// Content-Type = media-type
    /// ```
    ///
    /// # Example values
    /// * `text/html; charset=ISO-8859-4`
    ///
    /// # Examples
    /// ```
    /// use hyper::header::{Headers, ContentType};
    /// use hyper::mime::{Mime, TopLevel, SubLevel};
    ///
    /// let mut headers = Headers::new();
    ///
    /// headers.set(
    ///     ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![]))
    /// );
    /// ```
    /// ```
    /// use hyper::header::{Headers, ContentType};
    /// use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
    ///
    /// let mut headers = Headers::new();
    ///
    /// headers.set(
    ///     ContentType(Mime(TopLevel::Application, SubLevel::Json,
    ///                      vec![(Attr::Charset, Value::Utf8)]))
    /// );
    /// ```
    (ContentType, "Content-Type") => [Mime]

    test_content_type {
        test_header!(
            test1,
            // FIXME: Should be b"text/html; charset=ISO-8859-4" but mime crate lowercases
            // the whole value so parsing and formatting the value gives a different result
            vec![b"text/html; charset=iso-8859-4"],
            Some(HeaderField(Mime(
                TopLevel::Text,
                SubLevel::Html,
                vec![(Attr::Charset, Value::Ext("iso-8859-4".to_owned()))]))));
    }
}

impl ContentType {
    /// A constructor  to easily create a `Content-Type: application/json` header.
    #[inline]
    pub fn json() -> ContentType {
        ContentType(mime!(Application/Json))
    }

    /// A constructor  to easily create a `Content-Type: text/plain; charset=utf-8` header.
    #[inline]
    pub fn plaintext() -> ContentType {
        ContentType(mime!(Text/Plain; Charset=Utf8))
    }

    /// A constructor  to easily create a `Content-Type: text/html; charset=utf-8` header.
    #[inline]
    pub fn html() -> ContentType {
        ContentType(mime!(Text/Html; Charset=Utf8))
    }

    /// A constructor  to easily create a `Content-Type: application/www-form-url-encoded` header.
    #[inline]
    pub fn form_url_encoded() -> ContentType {
        ContentType(mime!(Application/WwwFormUrlEncoded))
    }
    /// A constructor  to easily create a `Content-Type: image/jpeg` header.
    #[inline]
    pub fn jpeg() -> ContentType {
        ContentType(mime!(Image/Jpeg))
    }

    /// A constructor  to easily create a `Content-Type: image/png` header.
    #[inline]
    pub fn png() -> ContentType {
        ContentType(mime!(Image/Png))
    }
}

bench_header!(bench, ContentType, { vec![b"application/json; charset=utf-8".to_vec()] });
<commit_msg>feat(headers): impl Eq for ContentType<commit_after>use mime::Mime;

header! {
    /// `Content-Type` header, defined in
    /// [RFC7231](http://tools.ietf.org/html/rfc7231#section-3.1.1.5)
    ///
    /// The `Content-Type` header field indicates the media type of the
    /// associated representation: either the representation enclosed in the
    /// message payload or the selected representation, as determined by the
    /// message semantics.  The indicated media type defines both the data
    /// format and how that data is intended to be processed by a recipient,
    /// within the scope of the received message semantics, after any content
    /// codings indicated by Content-Encoding are decoded.
    ///
    /// Although the `mime` crate allows the mime options to be any slice, this crate
    /// forces the use of Vec. This is to make sure the same header can't have more than 1 type. If
    /// this is an issue, it's possible to implement `Header` on a custom struct.
    ///
    /// # ABNF
    /// ```plain
    /// Content-Type = media-type
    /// ```
    ///
    /// # Example values
    /// * `text/html; charset=ISO-8859-4`
    ///
    /// # Examples
    /// ```
    /// use hyper::header::{Headers, ContentType};
    /// use hyper::mime::{Mime, TopLevel, SubLevel};
    ///
    /// let mut headers = Headers::new();
    ///
    /// headers.set(
    ///     ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![]))
    /// );
    /// ```
    /// ```
    /// use hyper::header::{Headers, ContentType};
    /// use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
    ///
    /// let mut headers = Headers::new();
    ///
    /// headers.set(
    ///     ContentType(Mime(TopLevel::Application, SubLevel::Json,
    ///                      vec![(Attr::Charset, Value::Utf8)]))
    /// );
    /// ```
    (ContentType, "Content-Type") => [Mime]

    test_content_type {
        test_header!(
            test1,
            // FIXME: Should be b"text/html; charset=ISO-8859-4" but mime crate lowercases
            // the whole value so parsing and formatting the value gives a different result
            vec![b"text/html; charset=iso-8859-4"],
            Some(HeaderField(Mime(
                TopLevel::Text,
                SubLevel::Html,
                vec![(Attr::Charset, Value::Ext("iso-8859-4".to_owned()))]))));
    }
}

impl ContentType {
    /// A constructor  to easily create a `Content-Type: application/json` header.
    #[inline]
    pub fn json() -> ContentType {
        ContentType(mime!(Application/Json))
    }

    /// A constructor  to easily create a `Content-Type: text/plain; charset=utf-8` header.
    #[inline]
    pub fn plaintext() -> ContentType {
        ContentType(mime!(Text/Plain; Charset=Utf8))
    }

    /// A constructor  to easily create a `Content-Type: text/html; charset=utf-8` header.
    #[inline]
    pub fn html() -> ContentType {
        ContentType(mime!(Text/Html; Charset=Utf8))
    }

    /// A constructor  to easily create a `Content-Type: application/www-form-url-encoded` header.
    #[inline]
    pub fn form_url_encoded() -> ContentType {
        ContentType(mime!(Application/WwwFormUrlEncoded))
    }
    /// A constructor  to easily create a `Content-Type: image/jpeg` header.
    #[inline]
    pub fn jpeg() -> ContentType {
        ContentType(mime!(Image/Jpeg))
    }

    /// A constructor  to easily create a `Content-Type: image/png` header.
    #[inline]
    pub fn png() -> ContentType {
        ContentType(mime!(Image/Png))
    }
}

impl Eq for ContentType {}

bench_header!(bench, ContentType, { vec![b"application/json; charset=utf-8".to_vec()] });
<|endoftext|>


<commit_before>
/// An error which can be returned when parsing an integer.
pub struct ParseDecimalError {

}
<commit_msg>corrected documentation for ParseDecimalError (still not really used)<commit_after>/// An error which can be returned when parsing a decimal.
pub struct ParseDecimalError {

}
<|endoftext|>