<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]);
}

//#[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>nevermind...<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;
               }
            }

         // 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));
}

<|endoftext|>


<commit_before>/*
 * Copyright 2019 Miklos Vajna. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

extern crate reqwest;
extern crate serde_json;
extern crate url;

use std::io::Write;

type BoxResult<T> = Result<T, Box<std::error::Error>>;

#[derive(Debug)]
struct OsmifyError {
    details: String
}

impl OsmifyError {
    fn new(msg: &str) -> OsmifyError {
        OsmifyError{details: msg.to_string()}
    }
}

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

impl std::error::Error for OsmifyError {
    fn description(&self) -> &str {
        &self.details
    }
}

fn query_turbo(query: &str) -> BoxResult<String> {
    let url = "http://overpass-api.de/api/interpreter";

    let client = reqwest::Client::new();
    let body = String::from(query);
    let mut buf = client.post(url)
        .body(body)
        .send()?;
    Ok(buf.text()?)
}

fn query_nominatim(query: &str) -> BoxResult<String> {
    let prefix = "http://nominatim.openstreetmap.org/search.php?";
    let encoded: String = url::form_urlencoded::Serializer::new(String::new())
        .append_pair("q", query)
        .append_pair("format", "json")
        .finish();
    let url = format!("{}{}", prefix, encoded);

    let mut buf = reqwest::get(url.as_str())?;

    Ok(buf.text()?)
}

fn osmify(query: &str) -> BoxResult<String> {
    let nominatim = query_nominatim(query)?;
    let json: serde_json::Value = match serde_json::from_str(&nominatim) {
        Ok(value) => value,
        Err(error) => {
            return Err(Box::new(OsmifyError::new(&format!("Failed to parse JSON from nominatim: {:?}", error))));
        },
    };
    let mut elements = json.as_array().ok_or("option::NoneError")?.clone();
    if elements.is_empty() {
        return Err(Box::new(OsmifyError::new("No results from nominatim")));
    }

    if elements.len() > 1 {
        // There are multiple elements, prefer buildings if possible.
        let buildings: Vec<serde_json::Value> = elements.iter().filter(|i| {
            let i = match i.as_object() {
                Some(value) => value,
                None => return false,
            };
            let class = match i.get("class") {
                Some(value) => value.as_str(),
                None => return false,
            };
            match class {
                Some(value) => value == "building",
                None => false,
            }
        } ).cloned().collect();

        if !buildings.is_empty() {
            elements = buildings;
        }
    }

    let element = elements[0].as_object().ok_or("option::NoneError")?;
    let lat = element["lat"].as_str().ok_or("option::NoneError")?;
    let lon = element["lon"].as_str().ok_or("option::NoneError")?;
    let object_type = element["osm_type"].as_str().ok_or("option::NoneError")?;
    let object_id = element["osm_id"].as_str().ok_or("option::NoneError")?;

    // Use overpass to get the properties of the object.
    let overpass_query = format!(r#"[out:json];
(
    {}({});
);
out body;"#, object_type, object_id);
    let turbo = query_turbo(&overpass_query)?;
    let json: serde_json::Value = match serde_json::from_str(&turbo) {
        Ok(value) => value,
        Err(error) => {
            return Err(Box::new(OsmifyError::new(&format!("Failed to parse JSON from overpass: {:?}", error))));
        },
    };
    let json = json.as_object().ok_or("option::NoneError")?;
    let elements = &json["elements"].as_array().ok_or("option::NoneError")?;
    if elements.is_empty() {
        return Err(Box::new(OsmifyError::new("No results from overpass")));
    }

    let element = &elements[0];
    let tags = element["tags"].as_object().ok_or("option::NoneError")?;
    let city = tags["addr:city"].as_str().ok_or("option::NoneError")?;
    let housenumber = tags["addr:housenumber"].as_str().ok_or("option::NoneError")?;
    let postcode = tags["addr:postcode"].as_str().ok_or("option::NoneError")?;
    let street = tags["addr:street"].as_str().ok_or("option::NoneError")?;
    let addr = format!("{} {}, {} {}", postcode, city, street, housenumber);

    // Print the result.
    Ok(format!("geo:{},{} ({})", lat, lon, addr))
}

fn spinner(rx: &std::sync::mpsc::Receiver<Result<String, String>>) -> BoxResult<()> {
    let spin_characters = vec!['\\', '|', '/', '-'];
    let mut spin_index = 0;
    loop {
        match rx.try_recv() {
            Ok(result) => {
                print!("\r");
                std::io::stdout().flush()?;
                let result = result?;
                println!("{}", result);
                return Ok(());
            },
            Err(_) => {
                print!("\r [{}] ", spin_characters[spin_index]);
                std::io::stdout().flush()?;
                spin_index = (spin_index + 1) % spin_characters.len();
                std::thread::sleep(std::time::Duration::from_millis(100));
            }
        }
    }
}

fn main() -> BoxResult<()> {
    let args: Vec<String> = std::env::args().collect();

    if args.len() > 1 {
        let (tx, rx) = std::sync::mpsc::channel();
        std::thread::spawn(move || {
            let result = osmify(&args[1]);
            match result {
                Ok(value) => tx.send(Ok(value)),
                Err(error) => tx.send(Err(format!("Failed to osmify: {:?}", error))),
            }
        });
        spinner(&rx)?;
    } else {
        println!("usage: addr-osmify <query>");
        println!();
        println!("e.g. addr-osmify 'Mészáros utca 58/a, Budapest'");
    }

    Ok(())
}
<commit_msg>addr-osmify-rust: run rustfmt on this<commit_after>/*
 * Copyright 2019 Miklos Vajna. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

extern crate reqwest;
extern crate serde_json;
extern crate url;

use std::io::Write;

type BoxResult<T> = Result<T, Box<std::error::Error>>;

#[derive(Debug)]
struct OsmifyError {
    details: String,
}

impl OsmifyError {
    fn new(msg: &str) -> OsmifyError {
        OsmifyError {
            details: msg.to_string(),
        }
    }
}

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

impl std::error::Error for OsmifyError {
    fn description(&self) -> &str {
        &self.details
    }
}

fn query_turbo(query: &str) -> BoxResult<String> {
    let url = "http://overpass-api.de/api/interpreter";

    let client = reqwest::Client::new();
    let body = String::from(query);
    let mut buf = client.post(url).body(body).send()?;
    Ok(buf.text()?)
}

fn query_nominatim(query: &str) -> BoxResult<String> {
    let prefix = "http://nominatim.openstreetmap.org/search.php?";
    let encoded: String = url::form_urlencoded::Serializer::new(String::new())
        .append_pair("q", query)
        .append_pair("format", "json")
        .finish();
    let url = format!("{}{}", prefix, encoded);

    let mut buf = reqwest::get(url.as_str())?;

    Ok(buf.text()?)
}

fn osmify(query: &str) -> BoxResult<String> {
    let nominatim = query_nominatim(query)?;
    let json: serde_json::Value = match serde_json::from_str(&nominatim) {
        Ok(value) => value,
        Err(error) => {
            return Err(Box::new(OsmifyError::new(&format!(
                "Failed to parse JSON from nominatim: {:?}",
                error
            ))));
        }
    };
    let mut elements = json.as_array().ok_or("option::NoneError")?.clone();
    if elements.is_empty() {
        return Err(Box::new(OsmifyError::new("No results from nominatim")));
    }

    if elements.len() > 1 {
        // There are multiple elements, prefer buildings if possible.
        let buildings: Vec<serde_json::Value> = elements
            .iter()
            .filter(|i| {
                let i = match i.as_object() {
                    Some(value) => value,
                    None => return false,
                };
                let class = match i.get("class") {
                    Some(value) => value.as_str(),
                    None => return false,
                };
                match class {
                    Some(value) => value == "building",
                    None => false,
                }
            })
            .cloned()
            .collect();

        if !buildings.is_empty() {
            elements = buildings;
        }
    }

    let element = elements[0].as_object().ok_or("option::NoneError")?;
    let lat = element["lat"].as_str().ok_or("option::NoneError")?;
    let lon = element["lon"].as_str().ok_or("option::NoneError")?;
    let object_type = element["osm_type"].as_str().ok_or("option::NoneError")?;
    let object_id = element["osm_id"].as_str().ok_or("option::NoneError")?;

    // Use overpass to get the properties of the object.
    let overpass_query = format!(
        r#"[out:json];
(
    {}({});
);
out body;"#,
        object_type, object_id
    );
    let turbo = query_turbo(&overpass_query)?;
    let json: serde_json::Value = match serde_json::from_str(&turbo) {
        Ok(value) => value,
        Err(error) => {
            return Err(Box::new(OsmifyError::new(&format!(
                "Failed to parse JSON from overpass: {:?}",
                error
            ))));
        }
    };
    let json = json.as_object().ok_or("option::NoneError")?;
    let elements = &json["elements"].as_array().ok_or("option::NoneError")?;
    if elements.is_empty() {
        return Err(Box::new(OsmifyError::new("No results from overpass")));
    }

    let element = &elements[0];
    let tags = element["tags"].as_object().ok_or("option::NoneError")?;
    let city = tags["addr:city"].as_str().ok_or("option::NoneError")?;
    let housenumber = tags["addr:housenumber"]
        .as_str()
        .ok_or("option::NoneError")?;
    let postcode = tags["addr:postcode"].as_str().ok_or("option::NoneError")?;
    let street = tags["addr:street"].as_str().ok_or("option::NoneError")?;
    let addr = format!("{} {}, {} {}", postcode, city, street, housenumber);

    // Print the result.
    Ok(format!("geo:{},{} ({})", lat, lon, addr))
}

fn spinner(rx: &std::sync::mpsc::Receiver<Result<String, String>>) -> BoxResult<()> {
    let spin_characters = vec!['\\', '|', '/', '-'];
    let mut spin_index = 0;
    loop {
        match rx.try_recv() {
            Ok(result) => {
                print!("\r");
                std::io::stdout().flush()?;
                let result = result?;
                println!("{}", result);
                return Ok(());
            }
            Err(_) => {
                print!("\r [{}] ", spin_characters[spin_index]);
                std::io::stdout().flush()?;
                spin_index = (spin_index + 1) % spin_characters.len();
                std::thread::sleep(std::time::Duration::from_millis(100));
            }
        }
    }
}

fn main() -> BoxResult<()> {
    let args: Vec<String> = std::env::args().collect();

    if args.len() > 1 {
        let (tx, rx) = std::sync::mpsc::channel();
        std::thread::spawn(move || {
            let result = osmify(&args[1]);
            match result {
                Ok(value) => tx.send(Ok(value)),
                Err(error) => tx.send(Err(format!("Failed to osmify: {:?}", error))),
            }
        });
        spinner(&rx)?;
    } else {
        println!("usage: addr-osmify <query>");
        println!();
        println!("e.g. addr-osmify 'Mészáros utca 58/a, Budapest'");
    }

    Ok(())
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

struct Foo<T: ?Sized> {
    a: u16,
    b: T
}

trait Bar {
    fn get(&self) -> usize;
}

impl Bar for usize {
    fn get(&self) -> usize { *self }
}

struct Baz<T: ?Sized> {
    a: T
}

#[repr(packed)]
struct Packed<T: ?Sized> {
    a: u8,
    b: T
}

struct HasDrop<T: ?Sized> {
    ptr: Box<usize>,
    data: T
}

fn main() {
    // Test that zero-offset works properly
    let b : Baz<usize> = Baz { a: 7 };
    assert_eq!(b.a.get(), 7);
    let b : &Baz<Bar> = &b;
    assert_eq!(b.a.get(), 7);

    // Test that the field is aligned properly
    let f : Foo<usize> = Foo { a: 0, b: 11 };
    assert_eq!(f.b.get(), 11);
    let ptr1 : *const u8 = &f.b as *const _ as *const u8;

    let f : &Foo<Bar> = &f;
    let ptr2 : *const u8 = &f.b as *const _ as *const u8;
    assert_eq!(f.b.get(), 11);

    // The pointers should be the same
    assert_eq!(ptr1, ptr2);

    // Test that nested DSTs work properly
    let f : Foo<Foo<usize>> = Foo { a: 0, b: Foo { a: 1, b: 17 }};
    assert_eq!(f.b.b.get(), 17);
    let f : &Foo<Foo<Bar>> = &f;
    assert_eq!(f.b.b.get(), 17);

    // Test that get the pointer via destructuring works

    let f : Foo<usize> = Foo { a: 0, b: 11 };
    let f : &Foo<Bar> = &f;
    let &Foo { a: _, b: ref bar } = f;
    assert_eq!(bar.get(), 11);

    // Make sure that drop flags don't screw things up

    let d : HasDrop<Baz<[i32; 4]>> = HasDrop {
        ptr: Box::new(0),
        data: Baz { a: [1,2,3,4] }
    };
    assert_eq!([1,2,3,4], d.data.a);

    let d : &HasDrop<Baz<[i32]>> = &d;
    assert_eq!(&[1,2,3,4], &d.data.a);
}
<commit_msg>removed unused struct<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

struct Foo<T: ?Sized> {
    a: u16,
    b: T
}

trait Bar {
    fn get(&self) -> usize;
}

impl Bar for usize {
    fn get(&self) -> usize { *self }
}

struct Baz<T: ?Sized> {
    a: T
}

struct HasDrop<T: ?Sized> {
    ptr: Box<usize>,
    data: T
}

fn main() {
    // Test that zero-offset works properly
    let b : Baz<usize> = Baz { a: 7 };
    assert_eq!(b.a.get(), 7);
    let b : &Baz<Bar> = &b;
    assert_eq!(b.a.get(), 7);

    // Test that the field is aligned properly
    let f : Foo<usize> = Foo { a: 0, b: 11 };
    assert_eq!(f.b.get(), 11);
    let ptr1 : *const u8 = &f.b as *const _ as *const u8;

    let f : &Foo<Bar> = &f;
    let ptr2 : *const u8 = &f.b as *const _ as *const u8;
    assert_eq!(f.b.get(), 11);

    // The pointers should be the same
    assert_eq!(ptr1, ptr2);

    // Test that nested DSTs work properly
    let f : Foo<Foo<usize>> = Foo { a: 0, b: Foo { a: 1, b: 17 }};
    assert_eq!(f.b.b.get(), 17);
    let f : &Foo<Foo<Bar>> = &f;
    assert_eq!(f.b.b.get(), 17);

    // Test that get the pointer via destructuring works

    let f : Foo<usize> = Foo { a: 0, b: 11 };
    let f : &Foo<Bar> = &f;
    let &Foo { a: _, b: ref bar } = f;
    assert_eq!(bar.get(), 11);

    // Make sure that drop flags don't screw things up

    let d : HasDrop<Baz<[i32; 4]>> = HasDrop {
        ptr: Box::new(0),
        data: Baz { a: [1,2,3,4] }
    };
    assert_eq!([1,2,3,4], d.data.a);

    let d : &HasDrop<Baz<[i32]>> = &d;
    assert_eq!(&[1,2,3,4], &d.data.a);
}
<|endoftext|>


<commit_before>// Copyright Dan Schatzberg, 2015. This file is part of Genesis.

// Genesis is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Genesis is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with Genesis.  If not, see <http://www.gnu.org/licenses/>.
use fixedvec::FixedVec;
use spin;
use super::{Frame, FrameAllocator, FrameRange, PAddr};

pub struct FirstFitAllocator<'a> {
    frames: &'a spin::Mutex<FixedVec<'a, FrameRange>>,
}

lazy_static! {
    static ref FRAMES: spin::Mutex<FixedVec<'static, FrameRange>> = {
        const FRAMES_SIZE: usize = 256;
        static mut FRAMES_MEM: [FrameRange; FRAMES_SIZE] = [FrameRange::new(
            Frame::down(PAddr::from_u64(0)), 0); FRAMES_SIZE];
        // Unsafe to take a mutable reference of a static.
        // We instantly store it behind a Mutex, so this is safe
        unsafe {
            spin::Mutex::new(FixedVec::new(&mut FRAMES_MEM))
        }
    };
    static ref ALLOCATOR: FirstFitAllocator<'static> = {
        FirstFitAllocator { frames: &FRAMES }
    };
}

impl FirstFitAllocator<'static> {
    pub fn get() -> &'static FirstFitAllocator<'static> {
        &ALLOCATOR
    }
}

impl<'a> FrameAllocator for FirstFitAllocator<'a> {
    fn allocate_manual(&self) -> Option<Frame> {
        self.allocate_range_manual(1).map(|range| range.start())
    }

    unsafe fn free_manual(&self, frame: Frame) {
        self.free_range_manual(FrameRange::new(frame, 1))
    }

    fn allocate_range_manual(&self, nframes: u64) -> Option<FrameRange> {
        let mut frames = self.frames.lock();
        frames.iter()
              .position(|range| range.nframes() >= nframes)
              .map(|index| {
                  let ret = FrameRange::new(frames[index].start(), nframes);
                  if frames[index].nframes() == nframes {
                      frames.remove(index);
                  } else {
                      frames[index].trim_front(nframes);
                  }
                  ret
              })
    }

    unsafe fn free_range_manual(&self, range: FrameRange) {
        let mut frames = self.frames.lock();
        let ind = {
            let slice = frames.as_slice();
            slice.binary_search_by(|r| r.partial_cmp(&range).unwrap())
                 .unwrap_err()
        };
        let prev_coalesce = if ind > 0 {
            if let Some(prev) = frames.get(ind - 1) {
                prev.end() == range.start()
            } else {
                false
            }
        } else {
            false
        };
        let next_coalesce = if ind < frames.len() {
            if let Some(next) = frames.get(ind) {
                range.end() == next.start()
            } else {
                false
            }
        } else {
            false
        };
        if !prev_coalesce && !next_coalesce {
            if frames.insert(ind, range).is_err() {
                warn!("No space to store freed range.\
                       It will be forgetten: {:?}",
                      range)
            }
        } else if prev_coalesce && !next_coalesce {
            let mut prev = frames.get_mut(ind - 1).unwrap();
            prev.push_back(range.nframes());
        } else if !prev_coalesce && next_coalesce {
            let mut next = frames.get_mut(ind).unwrap();
            next.push_front(range.nframes());
        } else {
            let nframes = frames.get(ind).unwrap().nframes() + range.nframes();
            {
                let mut prev = frames.get_mut(ind - 1).unwrap();
                prev.push_back(nframes);
            }
            frames.remove(ind);
        }
    }
}

#[cfg(test)]
mod test {
    use super::FirstFitAllocator;
    use fixedvec::FixedVec;
    use memory::{Frame, FrameAllocator, FrameRange, PAddr};
    use spin;

    #[test]
    fn test_get() {
        FirstFitAllocator::get();
    }

    const fn create_range(start_page: u64, nframes: u64) -> FrameRange {
        FrameRange::new(Frame { num: start_page }, nframes)
    }

    #[test]
    fn test_simple() {
        let mut space = [create_range(0, 0); 256];
        let frames = spin::Mutex::new(FixedVec::new(&mut space));
        let allocator = FirstFitAllocator { frames: &frames };
        let r = create_range(0, 1);
        unsafe { allocator.free_range_manual(r) };
        assert_eq!(allocator.allocate_range_manual(1).unwrap(), r);
    }

    #[test]
    fn test_prev_coalesce() {
        let mut space = [create_range(0, 0); 256];
        let frames = spin::Mutex::new(FixedVec::new(&mut space));
        let allocator = FirstFitAllocator { frames: &frames };
        unsafe { allocator.free_range_manual(create_range(0, 1)) };
        unsafe { allocator.free_range_manual(create_range(1, 1)) };
        assert_eq!(allocator.allocate_range_manual(2).unwrap(),
                   create_range(0, 2));
    }

    #[test]
    fn test_next_coalesce() {
        let mut space = [create_range(0, 0); 256];
        let frames = spin::Mutex::new(FixedVec::new(&mut space));
        let allocator = FirstFitAllocator { frames: &frames };
        unsafe { allocator.free_range_manual(create_range(1, 1)) };
        unsafe { allocator.free_range_manual(create_range(0, 1)) };
        assert_eq!(allocator.allocate_range_manual(2).unwrap(),
                   create_range(0, 2));
    }

    #[test]
    fn test_both_coalesce() {
        let mut space = [create_range(0, 0); 256];
        let frames = spin::Mutex::new(FixedVec::new(&mut space));
        let allocator = FirstFitAllocator { frames: &frames };
        unsafe { allocator.free_range_manual(create_range(0, 1)) };
        unsafe { allocator.free_range_manual(create_range(2, 1)) };
        unsafe { allocator.free_range_manual(create_range(1, 1)) };
        assert_eq!(allocator.allocate_range_manual(3).unwrap(),
                   create_range(0, 3));
    }
}
<commit_msg>Remove unnecessary use<commit_after>// Copyright Dan Schatzberg, 2015. This file is part of Genesis.

// Genesis is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Genesis is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with Genesis.  If not, see <http://www.gnu.org/licenses/>.
use fixedvec::FixedVec;
use spin;
use super::{Frame, FrameAllocator, FrameRange, PAddr};

pub struct FirstFitAllocator<'a> {
    frames: &'a spin::Mutex<FixedVec<'a, FrameRange>>,
}

lazy_static! {
    static ref FRAMES: spin::Mutex<FixedVec<'static, FrameRange>> = {
        const FRAMES_SIZE: usize = 256;
        static mut FRAMES_MEM: [FrameRange; FRAMES_SIZE] = [FrameRange::new(
            Frame::down(PAddr::from_u64(0)), 0); FRAMES_SIZE];
        // Unsafe to take a mutable reference of a static.
        // We instantly store it behind a Mutex, so this is safe
        unsafe {
            spin::Mutex::new(FixedVec::new(&mut FRAMES_MEM))
        }
    };
    static ref ALLOCATOR: FirstFitAllocator<'static> = {
        FirstFitAllocator { frames: &FRAMES }
    };
}

impl FirstFitAllocator<'static> {
    pub fn get() -> &'static FirstFitAllocator<'static> {
        &ALLOCATOR
    }
}

impl<'a> FrameAllocator for FirstFitAllocator<'a> {
    fn allocate_manual(&self) -> Option<Frame> {
        self.allocate_range_manual(1).map(|range| range.start())
    }

    unsafe fn free_manual(&self, frame: Frame) {
        self.free_range_manual(FrameRange::new(frame, 1))
    }

    fn allocate_range_manual(&self, nframes: u64) -> Option<FrameRange> {
        let mut frames = self.frames.lock();
        frames.iter()
              .position(|range| range.nframes() >= nframes)
              .map(|index| {
                  let ret = FrameRange::new(frames[index].start(), nframes);
                  if frames[index].nframes() == nframes {
                      frames.remove(index);
                  } else {
                      frames[index].trim_front(nframes);
                  }
                  ret
              })
    }

    unsafe fn free_range_manual(&self, range: FrameRange) {
        let mut frames = self.frames.lock();
        let ind = {
            let slice = frames.as_slice();
            slice.binary_search_by(|r| r.partial_cmp(&range).unwrap())
                 .unwrap_err()
        };
        let prev_coalesce = if ind > 0 {
            if let Some(prev) = frames.get(ind - 1) {
                prev.end() == range.start()
            } else {
                false
            }
        } else {
            false
        };
        let next_coalesce = if ind < frames.len() {
            if let Some(next) = frames.get(ind) {
                range.end() == next.start()
            } else {
                false
            }
        } else {
            false
        };
        if !prev_coalesce && !next_coalesce {
            if frames.insert(ind, range).is_err() {
                warn!("No space to store freed range.\
                       It will be forgetten: {:?}",
                      range)
            }
        } else if prev_coalesce && !next_coalesce {
            let mut prev = frames.get_mut(ind - 1).unwrap();
            prev.push_back(range.nframes());
        } else if !prev_coalesce && next_coalesce {
            let mut next = frames.get_mut(ind).unwrap();
            next.push_front(range.nframes());
        } else {
            let nframes = frames.get(ind).unwrap().nframes() + range.nframes();
            {
                let mut prev = frames.get_mut(ind - 1).unwrap();
                prev.push_back(nframes);
            }
            frames.remove(ind);
        }
    }
}

#[cfg(test)]
mod test {
    use super::FirstFitAllocator;
    use fixedvec::FixedVec;
    use memory::{Frame, FrameAllocator, FrameRange};
    use spin;

    #[test]
    fn test_get() {
        FirstFitAllocator::get();
    }

    const fn create_range(start_page: u64, nframes: u64) -> FrameRange {
        FrameRange::new(Frame { num: start_page }, nframes)
    }

    #[test]
    fn test_simple() {
        let mut space = [create_range(0, 0); 256];
        let frames = spin::Mutex::new(FixedVec::new(&mut space));
        let allocator = FirstFitAllocator { frames: &frames };
        let r = create_range(0, 1);
        unsafe { allocator.free_range_manual(r) };
        assert_eq!(allocator.allocate_range_manual(1).unwrap(), r);
    }

    #[test]
    fn test_prev_coalesce() {
        let mut space = [create_range(0, 0); 256];
        let frames = spin::Mutex::new(FixedVec::new(&mut space));
        let allocator = FirstFitAllocator { frames: &frames };
        unsafe { allocator.free_range_manual(create_range(0, 1)) };
        unsafe { allocator.free_range_manual(create_range(1, 1)) };
        assert_eq!(allocator.allocate_range_manual(2).unwrap(),
                   create_range(0, 2));
    }

    #[test]
    fn test_next_coalesce() {
        let mut space = [create_range(0, 0); 256];
        let frames = spin::Mutex::new(FixedVec::new(&mut space));
        let allocator = FirstFitAllocator { frames: &frames };
        unsafe { allocator.free_range_manual(create_range(1, 1)) };
        unsafe { allocator.free_range_manual(create_range(0, 1)) };
        assert_eq!(allocator.allocate_range_manual(2).unwrap(),
                   create_range(0, 2));
    }

    #[test]
    fn test_both_coalesce() {
        let mut space = [create_range(0, 0); 256];
        let frames = spin::Mutex::new(FixedVec::new(&mut space));
        let allocator = FirstFitAllocator { frames: &frames };
        unsafe { allocator.free_range_manual(create_range(0, 1)) };
        unsafe { allocator.free_range_manual(create_range(2, 1)) };
        unsafe { allocator.free_range_manual(create_range(1, 1)) };
        assert_eq!(allocator.allocate_range_manual(3).unwrap(),
                   create_range(0, 3));
    }
}
<|endoftext|>


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

extern crate commands;
extern crate readline;

use commands::parser::builder::{Command, CommandTree};
use commands::parser::nodes::Node;
use commands::parser::{ParseError, Parser};
use commands::tokenizer::tokenize;
use readline::readline;

fn main() {
    let mut tree = CommandTree::new();
    tree.command(Command::new("show").finalize());
    let root = tree.finalize();

    while let Ok(s) = readline(">> ") {
        if let Ok(tokens) = tokenize(&*s) {
            let mut parser = Parser::new(root.clone());
            match parser.parse(tokens) {
                Ok(_) => {}
                Err(ParseError::NoMatches(_, acceptable)) => {
                    print!("\nPossible options:\n");
                    for ref option in acceptable {
                        print!("  {} - {}\n", option.help_symbol(), option.help_text());
                    }
                }
                Err(ParseError::AmbiguousMatch(_, matches)) => {
                    print!("\nCan be interpreted as:\n");
                    for ref option in matches {
                        print!("  {} - {}\n", option.help_symbol(), option.help_text());
                    }
                }
            }
        }
        print!("\n");
    }
    print!("\nExiting.\n");
}
<commit_msg>Readline example: Verify and execute the parser as well.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate commands;
extern crate readline;

use commands::parser::builder::{Command, CommandTree};
use commands::parser::nodes::Node;
use commands::parser::{ParseError, Parser};
use commands::tokenizer::tokenize;
use readline::readline;

fn main() {
    let mut tree = CommandTree::new();
    tree.command(Command::new("show").finalize());
    let root = tree.finalize();

    while let Ok(s) = readline(">> ") {
        if let Ok(tokens) = tokenize(&*s) {
            let mut parser = Parser::new(root.clone());
            if let Err(err) = parser.parse(tokens) {
                match err {
                    ParseError::NoMatches(_, acceptable) => {
                        print!("\nPossible options:\n");
                        for ref option in acceptable {
                            print!("  {} - {}\n", option.help_symbol(), option.help_text());
                        }
                    }
                    ParseError::AmbiguousMatch(_, matches) => {
                        print!("\nCan be interpreted as:\n");
                        for ref option in matches {
                            print!("  {} - {}\n", option.help_symbol(), option.help_text());
                        }
                    }
                }
            } else if let Err(err) = parser.verify() {
                print!("{}\n", err);
            } else {
                parser.execute();
            }
        }
        print!("\n");
    }
    print!("\nExiting.\n");
}
<|endoftext|>


<commit_before>use super::prelude::*;

use crate::middleware::current_user::TrustedUserId;
use crate::models::{ApiToken, User};
use crate::util::errors::{internal, AppError, AppResult, ChainError, Unauthorized};

#[derive(Debug)]
pub struct AuthenticatedUser(i32, Option<i32>);

impl AuthenticatedUser {
    pub fn user_id(&self) -> i32 {
        self.0
    }

    pub fn api_token_id(&self) -> Option<i32> {
        self.1
    }

    pub fn find_user(&self, conn: &PgConnection) -> AppResult<User> {
        User::find(conn, self.user_id())
            .chain_error(|| internal("user_id from cookie or token not found in database"))
    }
}

impl<'a> UserAuthenticationExt for dyn Request + 'a {
    /// Obtain `CurrentUserIds` for the request or return an `Unauthorized` error
    fn authenticate(&self, conn: &PgConnection) -> AppResult<AuthenticatedUser> {
        if let Some(id) = self.extensions().find::<TrustedUserId>() {
            // A trusted user_id was provided by a signed cookie (or a test `MockCookieUser`)
            Ok(AuthenticatedUser(id.0, None))
        } else {
            // Otherwise, look for an `Authorization` header on the request
            if let Some(headers) = self.headers().find("Authorization") {
                ApiToken::find_by_api_token(conn, headers[0])
                    .map(|token| AuthenticatedUser(token.user_id, Some(token.id)))
                    // Convert a NotFound (or other database error) into Unauthorized
                    .map_err(|_| Box::new(Unauthorized) as Box<dyn AppError>)
            } else {
                // Unable to authenticate the user
                Err(Box::new(Unauthorized))
            }
        }
    }
}
<commit_msg>Address PR review comments<commit_after>use super::prelude::*;

use crate::middleware::current_user::TrustedUserId;
use crate::models::{ApiToken, User};
use crate::util::errors::{internal, AppError, AppResult, ChainError, Unauthorized};

#[derive(Debug)]
pub struct AuthenticatedUser {
    user_id: i32,
    token_id: Option<i32>,
}

impl AuthenticatedUser {
    pub fn user_id(&self) -> i32 {
        self.user_id
    }

    pub fn api_token_id(&self) -> Option<i32> {
        self.token_id
    }

    pub fn find_user(&self, conn: &PgConnection) -> AppResult<User> {
        User::find(conn, self.user_id())
            .chain_error(|| internal("user_id from cookie or token not found in database"))
    }
}

impl<'a> UserAuthenticationExt for dyn Request + 'a {
    /// Obtain `AuthenticatedUser` for the request or return an `Unauthorized` error
    fn authenticate(&self, conn: &PgConnection) -> AppResult<AuthenticatedUser> {
        if let Some(id) = self.extensions().find::<TrustedUserId>() {
            // A trusted user_id was provided by a signed cookie (or a test `MockCookieUser`)
            Ok(AuthenticatedUser {
                user_id: id.0,
                token_id: None,
            })
        } else {
            // Otherwise, look for an `Authorization` header on the request
            if let Some(headers) = self.headers().find("Authorization") {
                ApiToken::find_by_api_token(conn, headers[0])
                    .map(|token| AuthenticatedUser {
                        user_id: token.user_id,
                        token_id: Some(token.id),
                    })
                    // Convert a NotFound (or other database error) into Unauthorized
                    .map_err(|_| Box::new(Unauthorized) as Box<dyn AppError>)
            } else {
                // Unable to authenticate the user
                Err(Box::new(Unauthorized))
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate piston;
extern crate opengl_graphics;
extern crate graphics;
extern crate shader_version;
#[cfg(feature = "include_sdl2")]
extern crate sdl2_window;
#[cfg(feature = "include_glfw")]
extern crate glfw_window;
#[cfg(feature = "include_glutin")]
extern crate glutin_window;

use opengl_graphics::GlGraphics;
use graphics::{ Context, Graphics };
use std::cell::RefCell;
use piston::quack::Set;
use piston::window::{ WindowSettings, CaptureCursor };
use piston::input::Button;
use piston::input::keyboard::Key;
use piston::event::{
    PressEvent,
    ReleaseEvent,
    MouseCursorEvent,
    MouseScrollEvent,
    MouseRelativeEvent,
    TextEvent,
    ResizeEvent,
    FocusEvent,
    RenderEvent,
    UpdateEvent
};
use shader_version::OpenGL;
#[cfg(feature = "include_sdl2")]
use sdl2_window::Sdl2Window as Window;
#[cfg(feature = "include_glfw")]
use glfw_window::GlfwWindow as Window;
#[cfg(feature = "include_glutin")]
use glutin_window::GlutinWindow as Window;

fn main() {
    let opengl = OpenGL::_3_2;
    let window = Window::new(
        opengl,
        WindowSettings {
            title: "piston-examples/user_input".to_string(),
            size: [600, 600],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    println!("Press C to turn capture cursor on/off");

    let mut capture_cursor = false;
    let ref window = RefCell::new(window);
    let ref mut gl = GlGraphics::new(opengl);
    for e in piston::events(window) {
        if let Some(Button::Mouse(button)) = e.press_args() {
            println!("Pressed mouse button '{:?}'", button);
        }
        if let Some(Button::Keyboard(key)) = e.press_args() {
            if key == Key::C {
                println!("Turned capture cursor on");
                capture_cursor = !capture_cursor;
                window.set(CaptureCursor(capture_cursor));
            }

            println!("Pressed keyboard key '{:?}'", key);
        };
        if let Some(button) = e.release_args() {
            match button {
                Button::Keyboard(key) => println!("Released keyboard key '{:?}'", key),
                Button::Mouse(button) => println!("Released mouse button '{:?}'", button),
            }
        };
        e.mouse_cursor(|x, y| println!("Mouse moved '{} {}'", x, y));
        e.mouse_scroll(|dx, dy| println!("Scrolled mouse '{}, {}'", dx, dy));
        e.mouse_relative(|dx, dy| println!("Relative mouse moved '{} {}'", dx, dy));
        e.text(|text| println!("Typed '{}'", text));
        e.resize(|w, h| println!("Resized '{}, {}'", w, h));
        if let Some(focused) = e.focus_args() {
            if focused { println!("Gained focus"); }
            else { println!("Lost focus"); }
        };
        if let Some(args) = e.render_args() {
            gl.draw(
                [0, 0, args.width as i32, args.height as i32],
                |c, g| {
                    graphics::clear([1.0; 4], g);
                    draw_rectangles(&window, &c, g);
                }
            );
        }
        e.update(|_| {});
    }
}

fn draw_rectangles<G: Graphics>(
    window: &RefCell<Window>,
    c: &Context,
    g: &mut G,
) {
    use piston::window::{ Size, DrawSize };
    use piston::quack::Get;

    let rect_border = graphics::Rectangle::border([1.0, 0.0, 0.0, 1.0], 1.0);

    let Size([w, h]) = window.get();
    let DrawSize([dw, dh]) = window.get();
    let zoom = 0.2;

    // User coordinates.
    rect_border.draw([0.0, 0.0, w as f64 * zoom, h as f64 * zoom], c, g);
    let rect_border = graphics::Rectangle::border([0.0, 0.0, 1.0, 1.0], 1.0);
    rect_border.draw([w as f64 * zoom, 0.0, dw as f64 * zoom, dh as f64 * zoom], c, g);
}
<commit_msg>Updated "user_input" example to latest piston-graphics<commit_after>extern crate piston;
extern crate opengl_graphics;
extern crate graphics;
extern crate shader_version;
#[cfg(feature = "include_sdl2")]
extern crate sdl2_window;
#[cfg(feature = "include_glfw")]
extern crate glfw_window;
#[cfg(feature = "include_glutin")]
extern crate glutin_window;

use opengl_graphics::GlGraphics;
use graphics::{ Graphics };
use std::cell::RefCell;
use piston::quack::Set;
use piston::window::{ WindowSettings, CaptureCursor };
use piston::input::Button;
use piston::input::keyboard::Key;
use piston::event::{
    PressEvent,
    ReleaseEvent,
    MouseCursorEvent,
    MouseScrollEvent,
    MouseRelativeEvent,
    TextEvent,
    ResizeEvent,
    FocusEvent,
    RenderEvent,
    UpdateEvent
};
use shader_version::OpenGL;
#[cfg(feature = "include_sdl2")]
use sdl2_window::Sdl2Window as Window;
#[cfg(feature = "include_glfw")]
use glfw_window::GlfwWindow as Window;
#[cfg(feature = "include_glutin")]
use glutin_window::GlutinWindow as Window;

fn main() {
    let opengl = OpenGL::_3_2;
    let window = Window::new(
        opengl,
        WindowSettings {
            title: "piston-examples/user_input".to_string(),
            size: [600, 600],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    println!("Press C to turn capture cursor on/off");

    let mut capture_cursor = false;
    let ref window = RefCell::new(window);
    let ref mut gl = GlGraphics::new(opengl);
    for e in piston::events(window) {
        if let Some(Button::Mouse(button)) = e.press_args() {
            println!("Pressed mouse button '{:?}'", button);
        }
        if let Some(Button::Keyboard(key)) = e.press_args() {
            if key == Key::C {
                println!("Turned capture cursor on");
                capture_cursor = !capture_cursor;
                window.set(CaptureCursor(capture_cursor));
            }

            println!("Pressed keyboard key '{:?}'", key);
        };
        if let Some(button) = e.release_args() {
            match button {
                Button::Keyboard(key) => println!("Released keyboard key '{:?}'", key),
                Button::Mouse(button) => println!("Released mouse button '{:?}'", button),
            }
        };
        e.mouse_cursor(|x, y| println!("Mouse moved '{} {}'", x, y));
        e.mouse_scroll(|dx, dy| println!("Scrolled mouse '{}, {}'", dx, dy));
        e.mouse_relative(|dx, dy| println!("Relative mouse moved '{} {}'", dx, dy));
        e.text(|text| println!("Typed '{}'", text));
        e.resize(|w, h| println!("Resized '{}, {}'", w, h));
        if let Some(focused) = e.focus_args() {
            if focused { println!("Gained focus"); }
            else { println!("Lost focus"); }
        };
        if let Some(args) = e.render_args() {
            gl.draw(
                [0, 0, args.width as i32, args.height as i32],
                |_, g| {
                    graphics::clear([1.0; 4], g);
                    draw_rectangles(&window, g);
                }
            );
        }
        e.update(|_| {});
    }
}

fn draw_rectangles<G: Graphics>(
    window: &RefCell<Window>,
    g: &mut G,
) {
    use piston::window::{ Size, DrawSize };
    use piston::quack::Get;

    let rect_border = graphics::Rectangle::border([1.0, 0.0, 0.0, 1.0], 1.0);

    let Size([w, h]) = window.get();
    let DrawSize([dw, dh]) = window.get();
    let zoom = 0.2;

    // User coordinates.
    let draw_state = graphics::default_draw_state();
    let transform = graphics::abs_transform(w as f64, h as f64);
    rect_border.draw([0.0, 0.0, w as f64 * zoom, h as f64 * zoom],
        draw_state, transform, g);
    let rect_border = graphics::Rectangle::border([0.0, 0.0, 1.0, 1.0], 1.0);
    rect_border.draw([w as f64 * zoom, 0.0, dw as f64 * zoom, dh as f64 * zoom],
        draw_state, transform, g);
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::rc::Rc;
use na::{Translation, Identity};
use na;
use utils::data::uid_remap::{UidRemap, FastKey};
use utils::data::pair::{Pair, PairTWHash};
use utils::data::hash_map::HashMap;
use math::{Point, Vector};
use geometry::bounding_volume::{BoundingVolume, BoundingVolumeInterferencesCollector};
use geometry::partitioning::{DBVT, DBVTLeaf};
use geometry::ray::{Ray, RayCast, RayInterferencesCollector};
use geometry::point::{PointQuery, PointInterferencesCollector};
use broad_phase::BroadPhase;

struct DBVTBroadPhaseProxy<P, BV, T> {
    data:   T,
    leaf:   Rc<RefCell<DBVTLeaf<P, FastKey, BV>>>,
    active: isize // Negative => removed.
}

const DEACTIVATION_THRESHOLD: isize = 100;
const REMOVE_FROM_TREE: isize = -1;
const REMOVE_FROM_STREE: isize = -2;

/// Broad phase based on a Dynamic Bounding Volume Tree.
///
/// It uses two separate trees: one for static objects and which is never updated, and one for
/// moving objects.
pub struct DBVTBroadPhase<P: Point, BV, T> {
    proxies:    UidRemap<DBVTBroadPhaseProxy<P, BV, T>>,
    tree:       DBVT<P, FastKey, BV>, // DBVT for moving objects.
    stree:      DBVT<P, FastKey, BV>, // DBVT for static objects.
    pairs:      HashMap<Pair, (), PairTWHash>, // Pairs detected (FIXME: use a Vec instead?)
    margin:     <P::Vect as Vector>::Scalar, // The margin added to each bounding volume.
    update_off: usize, // Incremental pairs removal index.
    purge_all:  bool,

    // Just to avoid dynamic allocations.
    collector:         Vec<FastKey>,
    pairs_to_remove:   Vec<Pair>,
    proxies_to_remove: Vec<usize>,
    to_update:         Vec<(FastKey, BV)>,
}

impl<P, BV, T> DBVTBroadPhase<P, BV, T>
    where P:  Point,
          BV: 'static + BoundingVolume<<P::Vect as Vector>::Scalar> + Translation<P::Vect> + Clone {
    /// Creates a new broad phase based on a Dynamic Bounding Volume Tree.
    pub fn new(margin: <P::Vect as Vector>::Scalar, small_keys: bool)
               -> DBVTBroadPhase<P, BV, T> {
        DBVTBroadPhase {
            proxies:    UidRemap::new(small_keys),
            tree:       DBVT::new(),
            stree:      DBVT::new(),
            pairs:      HashMap::new(PairTWHash::new()),
            update_off: 0,
            purge_all:  false,
            collector:  Vec::new(),
            to_update:  Vec::new(),
            pairs_to_remove:   Vec::new(),
            proxies_to_remove: Vec::new(),
            margin:            margin
        }
    }

    /// Number of interferences detected by this broad phase.
    #[inline]
    pub fn num_interferences(&self) -> usize {
        self.pairs.len()
    }
}

impl<P, BV, T> BroadPhase<P, BV, T> for DBVTBroadPhase<P, BV, T>
    where P:  Point,
          BV: 'static + BoundingVolume<<P::Vect as Vector>::Scalar> + Translation<P::Vect> +
              RayCast<P, Identity> + PointQuery<P, Identity> + Clone {
    #[inline]
    fn deferred_add(&mut self, uid: usize, bv: BV, data: T) {
        let lbv = bv.loosened(self.margin.clone());
        let leaf: DBVTLeaf<P, FastKey, BV> = DBVTLeaf::new(lbv.clone(), FastKey::new_invalid());
        let leaf = Rc::new(RefCell::new(leaf));
        let proxy = DBVTBroadPhaseProxy {
            data:   data,
            leaf:   leaf.clone(),
            active: DEACTIVATION_THRESHOLD
        };

        let (proxy_key, _) = self.proxies.insert(uid, proxy);
        leaf.borrow_mut().object = proxy_key.clone();
        self.to_update.push((proxy_key, lbv));
    }

    fn deferred_remove(&mut self, uid: usize) {
        let proxy_key = match self.proxies.get_fast_key(uid) {
            None      => return,
            Some(uid) => uid
        };

        {
            let proxy = self.proxies.get_fast_mut(&proxy_key).unwrap();

            match proxy.active {
                // Already removed.
                REMOVE_FROM_TREE | REMOVE_FROM_STREE => { },
                // To remove from the static tree.
                0 => proxy.active = REMOVE_FROM_STREE,
                // To remove from the dynamic tree.
                _ => proxy.active = REMOVE_FROM_TREE
            }

            self.purge_all = true;
        }

        self.proxies_to_remove.push(uid);
    }

    fn update(&mut self, allow_proximity: &mut FnMut(&T, &T) -> bool, handler: &mut FnMut(&T, &T, bool)) {
        /*
         * Remove all the outdated nodes.
         */
        for &(ref id, ref bv) in self.to_update.iter().rev() {
            // FIXME: the `None` case may actually happen if the object is updated, then
            // removed, then the broad phase is updated.
            let proxy = self.proxies.get_fast_mut(id).expect("The proxy was not valid.");

            // If the activation number is < than the threshold then the leaf has not been removed
            // yet.
            if proxy.active == 0 {
                proxy.leaf.borrow_mut().bounding_volume = bv.clone();
                self.stree.remove(&mut proxy.leaf);
                proxy.active = DEACTIVATION_THRESHOLD;
            }
            else if proxy.active == REMOVE_FROM_TREE {
                self.tree.remove(&mut proxy.leaf);
            }
            else if proxy.active == REMOVE_FROM_STREE {
                self.stree.remove(&mut proxy.leaf);
            }
            else if proxy.active < DEACTIVATION_THRESHOLD {
                proxy.leaf.borrow_mut().bounding_volume = bv.clone();
                self.tree.remove(&mut proxy.leaf);
                proxy.active = DEACTIVATION_THRESHOLD;
            }
        }

        /*
         * Re-insert outdated nodes one by one and collect interferences at the same time.
         */
        for &(ref proxy_key1, _) in self.to_update.iter().rev() {
            let proxy1 = &self.proxies[*proxy_key1];

            if !proxy1.leaf.borrow().is_detached() {
                continue;
            }

            if proxy1.active < 0 {
                continue;
            }

            {
                let node1 = proxy1.leaf.borrow();
                let mut visitor = BoundingVolumeInterferencesCollector::new(
                    &node1.bounding_volume,
                    &mut self.collector);

                self.tree.visit(&mut visitor);
                self.stree.visit(&mut visitor);
            }

            // Event generation.
            for proxy_key2 in self.collector.iter() {
                let proxy2 = &self.proxies[*proxy_key2];
                let filtered_out = proxy2.active < 0 || !allow_proximity(&proxy1.data, &proxy2.data);

                if !filtered_out {
                    let mut trigger = false;

                    let _ = self.pairs.find_or_insert_lazy(
                        Pair::new(*proxy_key1, *proxy_key2),
                        || { trigger = true; Some(()) });

                    if trigger {
                        handler(&proxy1.data, &proxy2.data, true)
                    }
                }
            }

            self.collector.clear();
            self.tree.insert(proxy1.leaf.clone());
        }

        /*
         * Remove some of the outdated collisions.
         */
        // NOTE: the exact same code is used on `brute_force_bounding_volume_broad_phase.rs`.
        // Refactor that?
        if self.purge_all || (self.to_update.len() != 0 && self.pairs.len() != 0) {
            let len = self.pairs.len();
            let num_removals;

            if self.purge_all {
                self.update_off = 0;
                num_removals = len;
                self.purge_all = false;
            }
            else {
                num_removals = na::clamp(self.to_update.len(), len / 10, len);
            }

            for i in self.update_off .. self.update_off + num_removals {
                let id   = i % self.pairs.len();
                let elts = self.pairs.elements();
                let ids  = elts[id].key;

                let remove = {
                    let proxy1 = &self.proxies[ids.first];
                    let proxy2 = &self.proxies[ids.second];

                    let bv1 = &proxy1.leaf.borrow().bounding_volume;
                    let bv2 = &proxy2.leaf.borrow().bounding_volume;

                    let filtered_out = proxy1.active < 0 ||
                                       proxy2.active < 0 ||
                                       !allow_proximity(&proxy1.data, &proxy2.data);

                    if filtered_out || !bv1.intersects(bv2) {
                        handler(&proxy1.data, &proxy2.data, false);

                        true
                    }
                    else {
                        false
                    }
                };

                if remove {
                    self.pairs_to_remove.push(ids);
                }
            }

            self.update_off = if self.pairs.len() != 0 {
                (self.update_off + num_removals) % self.pairs.len()
            } else {
                0
            };
        }

        self.to_update.clear();

        /*
         * Actually remove the pairs.
         */
        for pair in self.pairs_to_remove.iter() {
            self.pairs.remove(pair);
        }
        self.pairs_to_remove.clear();

        /*
         * Update activation states.
         * FIXME: could we avoid having to iterate through _all_ the proxies at each update?
         * (for example, using a timestamp instead of a counter).
         */
        for (_, proxy) in self.proxies.iter_mut() {
            if proxy.active == 1 {
                proxy.active = 0;
                self.tree.remove(&mut proxy.leaf);
                self.stree.insert(proxy.leaf.clone());
            }
            else if proxy.active > 1 {
                proxy.active = proxy.active - 1;
            }
        }

        for uid in self.proxies_to_remove.iter() {
            if let Some((_, mut proxy)) = self.proxies.remove(*uid) {
                if proxy.active == REMOVE_FROM_TREE {
                    self.tree.remove(&mut proxy.leaf);
                }
                else {
                    assert!(proxy.active == REMOVE_FROM_STREE);
                    self.stree.remove(&mut proxy.leaf);
                }
            }
        }

        self.proxies_to_remove.clear();
    }

    fn deferred_set_bounding_volume(&mut self, uid: usize, bounding_volume: BV) {
        if let Some(proxy_key) = self.proxies.get_fast_key(uid) {
            let proxy = self.proxies.get_fast_mut(&proxy_key).unwrap();

            if proxy.active >= 0 {
                let needs_update = !proxy.leaf.borrow().bounding_volume.contains(&bounding_volume);

                if needs_update {
                    self.to_update.push((proxy_key, bounding_volume.loosened(self.margin)));
                }
                else if proxy.active != DEACTIVATION_THRESHOLD { // If == the object might already be on the update list.
                    if proxy.active == 0 {
                        self.stree.remove(&mut proxy.leaf);
                        self.tree.insert(proxy.leaf.clone());
                    }

                    proxy.active = DEACTIVATION_THRESHOLD - 1;
                }
            }
        }
    }

    fn deferred_recompute_all_proximities(&mut self) {
        for proxy in self.proxies.iter() {
            if proxy.1.active >= 0 {
                self.to_update.push((proxy.0, proxy.1.leaf.borrow().bounding_volume.clone()));
            }
        }
    }

    fn interferences_with_bounding_volume<'a>(&'a self, bv: &BV, out: &mut Vec<&'a T>) {
        let mut collector = Vec::new();

        {
            let mut visitor = BoundingVolumeInterferencesCollector::new(bv, &mut collector);

            self.tree.visit(&mut visitor);
            self.stree.visit(&mut visitor);
        }

        for l in collector.into_iter() {
            out.push(&self.proxies[l].data)
        }
    }

    fn interferences_with_ray<'a>(&'a self, ray: &Ray<P>, out: &mut Vec<&'a T>) {
        let mut collector = Vec::new();

        {
            let mut visitor = RayInterferencesCollector::new(ray, &mut collector);

            self.tree.visit(&mut visitor);
            self.stree.visit(&mut visitor);
        }

        for l in collector.into_iter() {
            out.push(&self.proxies[l].data)
        }
    }

    fn interferences_with_point<'a>(&'a self, point: &P, out: &mut Vec<&'a T>) {
        let mut collector = Vec::new();

        {
            let mut visitor = PointInterferencesCollector::new(point, &mut collector);

            self.tree.visit(&mut visitor);
            self.stree.visit(&mut visitor);
        }

        for l in collector.into_iter() {
            out.push(&self.proxies[l].data)
        }
    }
}
<commit_msg>Delay insersions to the DBVT broad phase.<commit_after>use std::cell::RefCell;
use std::rc::Rc;
use na::{Translation, Identity};
use na;
use utils::data::uid_remap::{UidRemap, FastKey};
use utils::data::pair::{Pair, PairTWHash};
use utils::data::hash_map::HashMap;
use math::{Point, Vector};
use geometry::bounding_volume::{BoundingVolume, BoundingVolumeInterferencesCollector};
use geometry::partitioning::{DBVT, DBVTLeaf};
use geometry::ray::{Ray, RayCast, RayInterferencesCollector};
use geometry::point::{PointQuery, PointInterferencesCollector};
use broad_phase::BroadPhase;

struct DBVTBroadPhaseProxy<P, BV, T> {
    data:   T,
    leaf:   Rc<RefCell<DBVTLeaf<P, FastKey, BV>>>,
    active: isize // Negative => removed.
}

const DEACTIVATION_THRESHOLD: isize = 100;
const REMOVE_FROM_TREE: isize = -1;
const REMOVE_FROM_STREE: isize = -2;

/// Broad phase based on a Dynamic Bounding Volume Tree.
///
/// It uses two separate trees: one for static objects and which is never updated, and one for
/// moving objects.
pub struct DBVTBroadPhase<P: Point, BV, T> {
    proxies:    UidRemap<DBVTBroadPhaseProxy<P, BV, T>>,
    tree:       DBVT<P, FastKey, BV>, // DBVT for moving objects.
    stree:      DBVT<P, FastKey, BV>, // DBVT for static objects.
    pairs:      HashMap<Pair, (), PairTWHash>, // Pairs detected (FIXME: use a Vec instead?)
    margin:     <P::Vect as Vector>::Scalar, // The margin added to each bounding volume.
    update_off: usize, // Incremental pairs removal index.
    purge_all:  bool,

    // Just to avoid dynamic allocations.
    collector:         Vec<FastKey>,
    pairs_to_remove:   Vec<Pair>,
    proxies_to_remove: Vec<usize>,
    to_update:         Vec<(FastKey, BV)>,
    to_add:            Vec<(usize, BV, T)>
}

impl<P, BV, T> DBVTBroadPhase<P, BV, T>
    where P:  Point,
          BV: 'static + BoundingVolume<<P::Vect as Vector>::Scalar> + Translation<P::Vect> + Clone {
    /// Creates a new broad phase based on a Dynamic Bounding Volume Tree.
    pub fn new(margin: <P::Vect as Vector>::Scalar, small_keys: bool)
               -> DBVTBroadPhase<P, BV, T> {
        DBVTBroadPhase {
            proxies:    UidRemap::new(small_keys),
            tree:       DBVT::new(),
            stree:      DBVT::new(),
            pairs:      HashMap::new(PairTWHash::new()),
            update_off: 0,
            purge_all:  false,
            collector:  Vec::new(),
            to_update:  Vec::new(),
            to_add:     Vec::new(),
            pairs_to_remove:   Vec::new(),
            proxies_to_remove: Vec::new(),
            margin:            margin
        }
    }

    /// Number of interferences detected by this broad phase.
    #[inline]
    pub fn num_interferences(&self) -> usize {
        self.pairs.len()
    }
}

impl<P, BV, T> BroadPhase<P, BV, T> for DBVTBroadPhase<P, BV, T>
    where P:  Point,
          BV: 'static + BoundingVolume<<P::Vect as Vector>::Scalar> + Translation<P::Vect> +
              RayCast<P, Identity> + PointQuery<P, Identity> + Clone {
    #[inline]
    fn deferred_add(&mut self, uid: usize, bv: BV, data: T) {
        self.to_add.push((uid, bv, data));
    }

    fn deferred_remove(&mut self, uid: usize) {
        let proxy_key = match self.proxies.get_fast_key(uid) {
            None      => return,
            Some(uid) => uid
        };

        {
            let proxy = self.proxies.get_fast_mut(&proxy_key).unwrap();

            match proxy.active {
                // Already removed.
                REMOVE_FROM_TREE | REMOVE_FROM_STREE => { },
                // To remove from the static tree.
                0 => proxy.active = REMOVE_FROM_STREE,
                // To remove from the dynamic tree.
                _ => proxy.active = REMOVE_FROM_TREE
            }

            self.purge_all = true;
        }

        self.proxies_to_remove.push(uid);
    }

    fn update(&mut self, allow_proximity: &mut FnMut(&T, &T) -> bool, handler: &mut FnMut(&T, &T, bool)) {
        /*
         * Perform additions.
         */
        for (uid, bv, data) in self.to_add.drain(..) {
            let lbv = bv.loosened(self.margin.clone());
            let leaf: DBVTLeaf<P, FastKey, BV> = DBVTLeaf::new(lbv.clone(), FastKey::new_invalid());
            let leaf = Rc::new(RefCell::new(leaf));
            let proxy = DBVTBroadPhaseProxy {
                data:   data,
                leaf:   leaf.clone(),
                active: DEACTIVATION_THRESHOLD
            };

            let (proxy_key, _) = self.proxies.insert(uid, proxy);
            leaf.borrow_mut().object = proxy_key.clone();
            self.to_update.push((proxy_key, lbv));
        }

        /*
         * Remove all the outdated nodes.
         */
        for &(ref id, ref bv) in self.to_update.iter().rev() {
            // FIXME: the `None` case may actually happen if the object is updated, then
            // removed, then the broad phase is updated.
            let proxy = self.proxies.get_fast_mut(id).expect("The proxy was not valid.");

            // If the activation number is < than the threshold then the leaf has not been removed
            // yet.
            if proxy.active == 0 {
                proxy.leaf.borrow_mut().bounding_volume = bv.clone();
                self.stree.remove(&mut proxy.leaf);
                proxy.active = DEACTIVATION_THRESHOLD;
            }
            else if proxy.active == REMOVE_FROM_TREE {
                self.tree.remove(&mut proxy.leaf);
            }
            else if proxy.active == REMOVE_FROM_STREE {
                self.stree.remove(&mut proxy.leaf);
            }
            else if proxy.active < DEACTIVATION_THRESHOLD {
                proxy.leaf.borrow_mut().bounding_volume = bv.clone();
                self.tree.remove(&mut proxy.leaf);
                proxy.active = DEACTIVATION_THRESHOLD;
            }
        }

        /*
         * Re-insert outdated nodes one by one and collect interferences at the same time.
         */
        for &(ref proxy_key1, _) in self.to_update.iter().rev() {
            let proxy1 = &self.proxies[*proxy_key1];

            if !proxy1.leaf.borrow().is_detached() {
                continue;
            }

            if proxy1.active < 0 {
                continue;
            }

            {
                let node1 = proxy1.leaf.borrow();
                let mut visitor = BoundingVolumeInterferencesCollector::new(
                    &node1.bounding_volume,
                    &mut self.collector);

                self.tree.visit(&mut visitor);
                self.stree.visit(&mut visitor);
            }

            // Event generation.
            for proxy_key2 in self.collector.iter() {
                let proxy2 = &self.proxies[*proxy_key2];
                let filtered_out = proxy2.active < 0 || !allow_proximity(&proxy1.data, &proxy2.data);

                if !filtered_out {
                    let mut trigger = false;

                    let _ = self.pairs.find_or_insert_lazy(
                        Pair::new(*proxy_key1, *proxy_key2),
                        || { trigger = true; Some(()) });

                    if trigger {
                        handler(&proxy1.data, &proxy2.data, true)
                    }
                }
            }

            self.collector.clear();
            self.tree.insert(proxy1.leaf.clone());
        }

        /*
         * Remove some of the outdated collisions.
         */
        // NOTE: the exact same code is used on `brute_force_bounding_volume_broad_phase.rs`.
        // Refactor that?
        if self.purge_all || (self.to_update.len() != 0 && self.pairs.len() != 0) {
            let len = self.pairs.len();
            let num_removals;

            if self.purge_all {
                self.update_off = 0;
                num_removals = len;
                self.purge_all = false;
            }
            else {
                num_removals = na::clamp(self.to_update.len(), len / 10, len);
            }

            for i in self.update_off .. self.update_off + num_removals {
                let id   = i % self.pairs.len();
                let elts = self.pairs.elements();
                let ids  = elts[id].key;

                let remove = {
                    let proxy1 = &self.proxies[ids.first];
                    let proxy2 = &self.proxies[ids.second];

                    let bv1 = &proxy1.leaf.borrow().bounding_volume;
                    let bv2 = &proxy2.leaf.borrow().bounding_volume;

                    let filtered_out = proxy1.active < 0 ||
                                       proxy2.active < 0 ||
                                       !allow_proximity(&proxy1.data, &proxy2.data);

                    if filtered_out || !bv1.intersects(bv2) {
                        handler(&proxy1.data, &proxy2.data, false);

                        true
                    }
                    else {
                        false
                    }
                };

                if remove {
                    self.pairs_to_remove.push(ids);
                }
            }

            self.update_off = if self.pairs.len() != 0 {
                (self.update_off + num_removals) % self.pairs.len()
            } else {
                0
            };
        }

        self.to_update.clear();

        /*
         * Actually remove the pairs.
         */
        for pair in self.pairs_to_remove.iter() {
            self.pairs.remove(pair);
        }
        self.pairs_to_remove.clear();

        /*
         * Update activation states.
         * FIXME: could we avoid having to iterate through _all_ the proxies at each update?
         * (for example, using a timestamp instead of a counter).
         */
        for (_, proxy) in self.proxies.iter_mut() {
            if proxy.active == 1 {
                proxy.active = 0;
                self.tree.remove(&mut proxy.leaf);
                self.stree.insert(proxy.leaf.clone());
            }
            else if proxy.active > 1 {
                proxy.active = proxy.active - 1;
            }
        }

        for uid in self.proxies_to_remove.iter() {
            if let Some((_, mut proxy)) = self.proxies.remove(*uid) {
                if proxy.active == REMOVE_FROM_TREE {
                    self.tree.remove(&mut proxy.leaf);
                }
                else {
                    assert!(proxy.active == REMOVE_FROM_STREE);
                    self.stree.remove(&mut proxy.leaf);
                }
            }
        }

        self.proxies_to_remove.clear();
    }

    fn deferred_set_bounding_volume(&mut self, uid: usize, bounding_volume: BV) {
        if let Some(proxy_key) = self.proxies.get_fast_key(uid) {
            let proxy = self.proxies.get_fast_mut(&proxy_key).unwrap();

            if proxy.active >= 0 {
                let needs_update = !proxy.leaf.borrow().bounding_volume.contains(&bounding_volume);

                if needs_update {
                    self.to_update.push((proxy_key, bounding_volume.loosened(self.margin)));
                }
                else if proxy.active != DEACTIVATION_THRESHOLD { // If == the object might already be on the update list.
                    if proxy.active == 0 {
                        self.stree.remove(&mut proxy.leaf);
                        self.tree.insert(proxy.leaf.clone());
                    }

                    proxy.active = DEACTIVATION_THRESHOLD - 1;
                }
            }
        }
    }

    fn deferred_recompute_all_proximities(&mut self) {
        for proxy in self.proxies.iter() {
            if proxy.1.active >= 0 {
                self.to_update.push((proxy.0, proxy.1.leaf.borrow().bounding_volume.clone()));
            }
        }
    }

    fn interferences_with_bounding_volume<'a>(&'a self, bv: &BV, out: &mut Vec<&'a T>) {
        let mut collector = Vec::new();

        {
            let mut visitor = BoundingVolumeInterferencesCollector::new(bv, &mut collector);

            self.tree.visit(&mut visitor);
            self.stree.visit(&mut visitor);
        }

        for l in collector.into_iter() {
            out.push(&self.proxies[l].data)
        }
    }

    fn interferences_with_ray<'a>(&'a self, ray: &Ray<P>, out: &mut Vec<&'a T>) {
        let mut collector = Vec::new();

        {
            let mut visitor = RayInterferencesCollector::new(ray, &mut collector);

            self.tree.visit(&mut visitor);
            self.stree.visit(&mut visitor);
        }

        for l in collector.into_iter() {
            out.push(&self.proxies[l].data)
        }
    }

    fn interferences_with_point<'a>(&'a self, point: &P, out: &mut Vec<&'a T>) {
        let mut collector = Vec::new();

        {
            let mut visitor = PointInterferencesCollector::new(point, &mut collector);

            self.tree.visit(&mut visitor);
            self.stree.visit(&mut visitor);
        }

        for l in collector.into_iter() {
            out.push(&self.proxies[l].data)
        }
    }
}
<|endoftext|>


<commit_before>extern crate proc_macro;

// spell-checker:ignore () SIGPIPE uucore uumain uutils

//## rust proc-macro background info
//* ref: <https://dev.to/naufraghi/procedural-macro-in-rust-101-k3f> @@ <http://archive.is/Vbr5e>
//* ref: [path construction from LitStr](https://oschwald.github.io/maxminddb-rust/syn/struct.LitStr.html) @@ <http://archive.is/8YDua>

//## proc_dbg macro
//* used to help debug the compile-time proc_macro code

#[cfg(feature = "debug")]
macro_rules! proc_dbg {
    ($x:expr) => {
        dbg!($x)
    };
}
#[cfg(not(feature = "debug"))]
macro_rules! proc_dbg {
    ($x:expr) => {
        std::convert::identity($x)
    };
}

//## main!()

// main!( EXPR )
// generates a `main()` function for utilities within the uutils group
// EXPR == syn::Expr::Lit::String | syn::Expr::Path::Ident ~ EXPR contains the lexical path to the utility `uumain()` function
//* NOTE: EXPR is ultimately expected to be a multi-segment lexical path (eg, `crate::func`); so, if a single segment path is provided, a trailing "::uumain" is automatically added
//* for more generic use (and future use of "eager" macros), EXPR may be in either STRING or IDENT form

struct Tokens {
    expr: syn::Expr,
}

impl syn::parse::Parse for Tokens {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        Ok(Tokens {
            expr: input.parse()?,
        })
    }
}

#[proc_macro]
pub fn main(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let Tokens { expr } = syn::parse_macro_input!(stream as Tokens);
    proc_dbg!(&expr);

    const ARG_PANIC_TEXT: &str =
        "expected ident lexical path (or a literal string version) to 'uumain()' as argument";

    // match EXPR as a string literal or an ident path, o/w panic!()
    let mut expr = match expr {
        syn::Expr::Lit(expr_lit) => match expr_lit.lit {
            syn::Lit::Str(ref lit_str) => lit_str.parse::<syn::ExprPath>().unwrap(),
            _ => panic!(ARG_PANIC_TEXT),
        },
        syn::Expr::Path(expr_path) => expr_path,
        _ => panic!(ARG_PANIC_TEXT),
    };
    proc_dbg!(&expr);

    // for a single segment ExprPath argument, add trailing '::uumain' segment
    if expr.path.segments.len() < 2 {
        expr = syn::parse_quote!( #expr::uumain );
    };
    proc_dbg!(&expr);

    let f = quote::quote! { #expr(uucore::args().collect()) };
    proc_dbg!(&f);

    // generate a uutils utility `main()` function, tailored for the calling utility
    let result = quote::quote! {
        fn main() {
            use std::io::Write;
            uucore::panic::mute_sigpipe_panic(); // suppress extraneous error output for SIGPIPE failures/panics
            let code = #f; // execute utility code
            std::io::stdout().flush().expect("could not flush stdout"); // (defensively) flush stdout for utility prior to exit; see <https://github.com/rust-lang/rust/issues/23818>
            std::process::exit(code);
        }
    };
    proc_macro::TokenStream::from(result)
}
<commit_msg>build/uucore_procs ~ fix proc_dbg!() for MinSRV of v1.31.0<commit_after>extern crate proc_macro;

// spell-checker:ignore () SIGPIPE uucore uumain uutils

//## rust proc-macro background info
//* ref: <https://dev.to/naufraghi/procedural-macro-in-rust-101-k3f> @@ <http://archive.is/Vbr5e>
//* ref: [path construction from LitStr](https://oschwald.github.io/maxminddb-rust/syn/struct.LitStr.html) @@ <http://archive.is/8YDua>

//## proc_dbg macro
//* used to help debug the compile-time proc_macro code

#[cfg(feature = "debug")]
macro_rules! proc_dbg {
    ($x:expr) => {
        dbg!($x)
    };
}
#[cfg(not(feature = "debug"))]
macro_rules! proc_dbg {
    ($x:expr) => {
        $x
    };
}

//## main!()

// main!( EXPR )
// generates a `main()` function for utilities within the uutils group
// EXPR == syn::Expr::Lit::String | syn::Expr::Path::Ident ~ EXPR contains the lexical path to the utility `uumain()` function
//* NOTE: EXPR is ultimately expected to be a multi-segment lexical path (eg, `crate::func`); so, if a single segment path is provided, a trailing "::uumain" is automatically added
//* for more generic use (and future use of "eager" macros), EXPR may be in either STRING or IDENT form

struct Tokens {
    expr: syn::Expr,
}

impl syn::parse::Parse for Tokens {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        Ok(Tokens {
            expr: input.parse()?,
        })
    }
}

#[proc_macro]
pub fn main(stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let Tokens { expr } = syn::parse_macro_input!(stream as Tokens);
    proc_dbg!(&expr);

    const ARG_PANIC_TEXT: &str =
        "expected ident lexical path (or a literal string version) to 'uumain()' as argument";

    // match EXPR as a string literal or an ident path, o/w panic!()
    let mut expr = match expr {
        syn::Expr::Lit(expr_lit) => match expr_lit.lit {
            syn::Lit::Str(ref lit_str) => lit_str.parse::<syn::ExprPath>().unwrap(),
            _ => panic!(ARG_PANIC_TEXT),
        },
        syn::Expr::Path(expr_path) => expr_path,
        _ => panic!(ARG_PANIC_TEXT),
    };
    proc_dbg!(&expr);

    // for a single segment ExprPath argument, add trailing '::uumain' segment
    if expr.path.segments.len() < 2 {
        expr = syn::parse_quote!( #expr::uumain );
    };
    proc_dbg!(&expr);

    let f = quote::quote! { #expr(uucore::args().collect()) };
    proc_dbg!(&f);

    // generate a uutils utility `main()` function, tailored for the calling utility
    let result = quote::quote! {
        fn main() {
            use std::io::Write;
            uucore::panic::mute_sigpipe_panic(); // suppress extraneous error output for SIGPIPE failures/panics
            let code = #f; // execute utility code
            std::io::stdout().flush().expect("could not flush stdout"); // (defensively) flush stdout for utility prior to exit; see <https://github.com/rust-lang/rust/issues/23818>
            std::process::exit(code);
        }
    };
    proc_macro::TokenStream::from(result)
}
<|endoftext|>