<commit_before>//! FIXME: write short doc here

use std::{
    env,
    path::{Path, PathBuf},
    process::Command,
};

use ra_arena::{impl_arena_id, Arena, RawId};

use crate::Result;

#[derive(Default, Debug, Clone)]
pub struct Sysroot {
    crates: Arena<SysrootCrate, SysrootCrateData>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SysrootCrate(RawId);
impl_arena_id!(SysrootCrate);

#[derive(Debug, Clone)]
struct SysrootCrateData {
    name: String,
    root: PathBuf,
    deps: Vec<SysrootCrate>,
}

impl Sysroot {
    pub fn core(&self) -> Option<SysrootCrate> {
        self.by_name("core")
    }

    pub fn alloc(&self) -> Option<SysrootCrate> {
        self.by_name("alloc")
    }

    pub fn std(&self) -> Option<SysrootCrate> {
        self.by_name("std")
    }

    pub fn proc_macro(&self) -> Option<SysrootCrate> {
        self.by_name("proc_macro")
    }

    pub fn crates<'a>(&'a self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIterator + 'a {
        self.crates.iter().map(|(id, _data)| id)
    }

    pub fn discover(cargo_toml: &Path) -> Result<Sysroot> {
        let src = try_find_src_path(cargo_toml)?;

        if !src.exists() {
            Err(format!(
                "can't load standard library from sysroot\n\
                 {}\n\
                 (discovered via `rustc --print sysroot`)\n\
                 try running `rustup component add rust-src` or set `RUST_SRC_PATH`",
                src.display(),
            ))?;
        }

        let mut sysroot = Sysroot { crates: Arena::default() };
        for name in SYSROOT_CRATES.trim().lines() {
            let root = src.join(format!("lib{}", name)).join("lib.rs");
            if root.exists() {
                sysroot.crates.alloc(SysrootCrateData {
                    name: name.into(),
                    root,
                    deps: Vec::new(),
                });
            }
        }
        if let Some(std) = sysroot.std() {
            for dep in STD_DEPS.trim().lines() {
                if let Some(dep) = sysroot.by_name(dep) {
                    sysroot.crates[std].deps.push(dep)
                }
            }
        }
        if let Some(alloc) = sysroot.by_name("alloc") {
            if let Some(core) = sysroot.core() {
                sysroot.crates[alloc].deps.push(core);
            }
        }
        Ok(sysroot)
    }

    fn by_name(&self, name: &str) -> Option<SysrootCrate> {
        self.crates.iter().find(|(_id, data)| data.name == name).map(|(id, _data)| id)
    }
}

fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> {
    if let Ok(path) = env::var("RUST_SRC_PATH") {
        return Ok(path.into());
    }

    let rustc_output = Command::new("rustc")
        .current_dir(cargo_toml.parent().unwrap())
        .args(&["--print", "sysroot"])
        .output()?;
    if !rustc_output.status.success() {
        Err("failed to locate sysroot")?;
    }
    let stdout = String::from_utf8(rustc_output.stdout)?;
    let sysroot_path = Path::new(stdout.trim());
    Ok(sysroot_path.join("lib/rustlib/src/rust/src"))
}

impl SysrootCrate {
    pub fn name(self, sysroot: &Sysroot) -> &str {
        &sysroot.crates[self].name
    }
    pub fn root(self, sysroot: &Sysroot) -> &Path {
        sysroot.crates[self].root.as_path()
    }
    pub fn root_dir(self, sysroot: &Sysroot) -> &Path {
        self.root(sysroot).parent().unwrap()
    }
    pub fn deps<'a>(self, sysroot: &'a Sysroot) -> impl Iterator<Item = SysrootCrate> + 'a {
        sysroot.crates[self].deps.iter().copied()
    }
}

const SYSROOT_CRATES: &str = "
std
core
alloc
collections
libc
panic_unwind
proc_macro
rustc_unicode
std_unicode
test
alloc_jemalloc
alloc_system
compiler_builtins
getopts
panic_unwind
panic_abort
rand
term
unwind
build_helper
rustc_asan
rustc_lsan
rustc_msan
rustc_tsan
syntax";

const STD_DEPS: &str = "
alloc
alloc_jemalloc
alloc_system
core
panic_abort
rand
compiler_builtins
unwind
rustc_asan
rustc_lsan
rustc_msan
rustc_tsan
build_helper";
<commit_msg>More specific error if `rustc --print sysroot` fails<commit_after>//! FIXME: write short doc here

use std::{
    env,
    path::{Path, PathBuf},
    process::Command,
};

use ra_arena::{impl_arena_id, Arena, RawId};

use crate::Result;

#[derive(Default, Debug, Clone)]
pub struct Sysroot {
    crates: Arena<SysrootCrate, SysrootCrateData>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SysrootCrate(RawId);
impl_arena_id!(SysrootCrate);

#[derive(Debug, Clone)]
struct SysrootCrateData {
    name: String,
    root: PathBuf,
    deps: Vec<SysrootCrate>,
}

impl Sysroot {
    pub fn core(&self) -> Option<SysrootCrate> {
        self.by_name("core")
    }

    pub fn alloc(&self) -> Option<SysrootCrate> {
        self.by_name("alloc")
    }

    pub fn std(&self) -> Option<SysrootCrate> {
        self.by_name("std")
    }

    pub fn proc_macro(&self) -> Option<SysrootCrate> {
        self.by_name("proc_macro")
    }

    pub fn crates<'a>(&'a self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIterator + 'a {
        self.crates.iter().map(|(id, _data)| id)
    }

    pub fn discover(cargo_toml: &Path) -> Result<Sysroot> {
        let src = try_find_src_path(cargo_toml)?;

        if !src.exists() {
            Err(format!(
                "can't load standard library from sysroot\n\
                 {}\n\
                 (discovered via `rustc --print sysroot`)\n\
                 try running `rustup component add rust-src` or set `RUST_SRC_PATH`",
                src.display(),
            ))?;
        }

        let mut sysroot = Sysroot { crates: Arena::default() };
        for name in SYSROOT_CRATES.trim().lines() {
            let root = src.join(format!("lib{}", name)).join("lib.rs");
            if root.exists() {
                sysroot.crates.alloc(SysrootCrateData {
                    name: name.into(),
                    root,
                    deps: Vec::new(),
                });
            }
        }
        if let Some(std) = sysroot.std() {
            for dep in STD_DEPS.trim().lines() {
                if let Some(dep) = sysroot.by_name(dep) {
                    sysroot.crates[std].deps.push(dep)
                }
            }
        }
        if let Some(alloc) = sysroot.by_name("alloc") {
            if let Some(core) = sysroot.core() {
                sysroot.crates[alloc].deps.push(core);
            }
        }
        Ok(sysroot)
    }

    fn by_name(&self, name: &str) -> Option<SysrootCrate> {
        self.crates.iter().find(|(_id, data)| data.name == name).map(|(id, _data)| id)
    }
}

fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> {
    if let Ok(path) = env::var("RUST_SRC_PATH") {
        return Ok(path.into());
    }

    let rustc_output = Command::new("rustc")
        .current_dir(cargo_toml.parent().unwrap())
        .args(&["--print", "sysroot"])
        .output()
        .map_err(|e| format!("rustc --print sysroot failed: {}", e))?;
    if !rustc_output.status.success() {
        Err("failed to locate sysroot")?;
    }
    let stdout = String::from_utf8(rustc_output.stdout)?;
    let sysroot_path = Path::new(stdout.trim());
    Ok(sysroot_path.join("lib/rustlib/src/rust/src"))
}

impl SysrootCrate {
    pub fn name(self, sysroot: &Sysroot) -> &str {
        &sysroot.crates[self].name
    }
    pub fn root(self, sysroot: &Sysroot) -> &Path {
        sysroot.crates[self].root.as_path()
    }
    pub fn root_dir(self, sysroot: &Sysroot) -> &Path {
        self.root(sysroot).parent().unwrap()
    }
    pub fn deps<'a>(self, sysroot: &'a Sysroot) -> impl Iterator<Item = SysrootCrate> + 'a {
        sysroot.crates[self].deps.iter().copied()
    }
}

const SYSROOT_CRATES: &str = "
std
core
alloc
collections
libc
panic_unwind
proc_macro
rustc_unicode
std_unicode
test
alloc_jemalloc
alloc_system
compiler_builtins
getopts
panic_unwind
panic_abort
rand
term
unwind
build_helper
rustc_asan
rustc_lsan
rustc_msan
rustc_tsan
syntax";

const STD_DEPS: &str = "
alloc
alloc_jemalloc
alloc_system
core
panic_abort
rand
compiler_builtins
unwind
rustc_asan
rustc_lsan
rustc_msan
rustc_tsan
build_helper";
<|endoftext|>


<commit_before>//! string handles parsing of GPX-spec strings.

use errors::*;
use std::io::Read;
use xml::reader::XmlEvent;

use parser::verify_starting_tag;
use parser::Context;

/// consume consumes a single string as tag content.
pub fn consume<R: Read>(
    context: &mut Context<R>,
    tagname: &'static str,
    allow_empty: bool,
) -> Result<String> {
    let mut string: Option<String> = None;
    if allow_empty {
        string = Some("".to_string());
    }
    verify_starting_tag(context, tagname)?;

    for event in context.reader() {
        match event.chain_err(|| "error while parsing XML")? {
            XmlEvent::StartElement { ref name, .. } => {
                bail!(ErrorKind::InvalidChildElement(
                    name.local_name.clone(),
                    tagname
                ));
            }
            XmlEvent::Characters(content) => string = Some(content),
            XmlEvent::EndElement { ref name } => {
                ensure!(
                    name.local_name == tagname,
                    ErrorKind::InvalidClosingTag(name.local_name.clone(), tagname)
                );
                return string.ok_or("no content inside string".into());
            }
            _ => {}
        }
    }
    bail!(ErrorKind::MissingClosingTag(tagname));
}

#[cfg(test)]
mod tests {
    use std::io::BufReader;

    use super::consume;
    use GpxVersion;

    #[test]
    fn consume_simple_string() {
        let result = consume!("<string>hello world</string>", GpxVersion::Gpx11, "string", false);

        assert!(result.is_ok());
        assert_eq!(result.unwrap(), "hello world");
    }

    #[test]
    fn consume_new_tag() {
        // cannot start new tag inside string
        let result = consume!("<foo>bar<baz></baz></foo>", GpxVersion::Gpx11, "foo", false);

        assert!(result.is_err());
    }

    #[test]
    fn consume_start_tag() {
        // must have starting tag
        let result = consume!("bar</foo>", GpxVersion::Gpx11, "foo", false);

        assert!(result.is_err());
    }

    #[test]
    fn consume_end_tag() {
        // must have ending tag
        let result = consume!("<foo>bar", GpxVersion::Gpx11, "foo", false);

        assert!(result.is_err());
    }

    #[test]
    fn consume_no_body() {
        // must have string content
        let result = consume!("<foo></foo>", GpxVersion::Gpx11, "foo", false);

        assert!(result.is_err());
    }

    #[test]
    fn consume_different_ending_tag() {
        // this is just illegal
        let result = consume!("<foo></foobar>", GpxVersion::Gpx11, "foo", false);

        assert!(result.is_err());
    }
}
<commit_msg>fix cargo fmt issue<commit_after>//! string handles parsing of GPX-spec strings.

use errors::*;
use std::io::Read;
use xml::reader::XmlEvent;

use parser::verify_starting_tag;
use parser::Context;

/// consume consumes a single string as tag content.
pub fn consume<R: Read>(
    context: &mut Context<R>,
    tagname: &'static str,
    allow_empty: bool,
) -> Result<String> {
    let mut string: Option<String> = None;
    if allow_empty {
        string = Some("".to_string());
    }
    verify_starting_tag(context, tagname)?;

    for event in context.reader() {
        match event.chain_err(|| "error while parsing XML")? {
            XmlEvent::StartElement { ref name, .. } => {
                bail!(ErrorKind::InvalidChildElement(
                    name.local_name.clone(),
                    tagname
                ));
            }
            XmlEvent::Characters(content) => string = Some(content),
            XmlEvent::EndElement { ref name } => {
                ensure!(
                    name.local_name == tagname,
                    ErrorKind::InvalidClosingTag(name.local_name.clone(), tagname)
                );
                return string.ok_or("no content inside string".into());
            }
            _ => {}
        }
    }
    bail!(ErrorKind::MissingClosingTag(tagname));
}

#[cfg(test)]
mod tests {
    use std::io::BufReader;

    use super::consume;
    use GpxVersion;

    #[test]
    fn consume_simple_string() {
        let result = consume!(
            "<string>hello world</string>",
            GpxVersion::Gpx11,
            "string",
            false
        );

        assert!(result.is_ok());
        assert_eq!(result.unwrap(), "hello world");
    }

    #[test]
    fn consume_new_tag() {
        // cannot start new tag inside string
        let result = consume!("<foo>bar<baz></baz></foo>", GpxVersion::Gpx11, "foo", false);

        assert!(result.is_err());
    }

    #[test]
    fn consume_start_tag() {
        // must have starting tag
        let result = consume!("bar</foo>", GpxVersion::Gpx11, "foo", false);

        assert!(result.is_err());
    }

    #[test]
    fn consume_end_tag() {
        // must have ending tag
        let result = consume!("<foo>bar", GpxVersion::Gpx11, "foo", false);

        assert!(result.is_err());
    }

    #[test]
    fn consume_no_body() {
        // must have string content
        let result = consume!("<foo></foo>", GpxVersion::Gpx11, "foo", false);

        assert!(result.is_err());
    }

    #[test]
    fn consume_different_ending_tag() {
        // this is just illegal
        let result = consume!("<foo></foobar>", GpxVersion::Gpx11, "foo", false);

        assert!(result.is_err());
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::str::FromStr;

use hyper::Uri;

use client::{self, ApiClient};

static DATASTORE_ROOT: &str = "https://datastore.googleapis.com/v1";

pub struct DatastoreService {}
pub type Hub<'a> = client::Hub<'a, DatastoreService>;

pub type ValueMap = HashMap<String, Value>;

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct BeginTransactionRequest {}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct BeginTransactionResponse {
    pub transaction: String,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct CommitRequest {
    pub transaction: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub mode: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub mutations: Option<Vec<Mutation>>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct CommitResponse {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub mutation_results: Option<Vec<MutationResult>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub index_updates: Option<i32>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
struct RunQueryRequest {
    partition_id: PartitionId,
    read_options: ReadOptions,

    #[serde(skip_serializing_if = "Option::is_none")]
    gql_query: Option<GqlQuery>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
struct GqlQuery {
    query_string: String,
    allow_literals: bool,
    named_bindings: HashMap<String, GqlQueryParameter>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
struct GqlQueryParameter {
    value: Value,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RunQueryResponse {
    pub batch: QueryResultBatch,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct QueryResultBatch {
    pub entity_results: Option<Vec<EntityResult>>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Mutation {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub insert: Option<Entity>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub upsert: Option<Entity>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub update: Option<Entity>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub base_version: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub delete: Option<Key>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct MutationResult {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub version: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub conflict_detected: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub key: Option<Key>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct LookupRequest {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub keys: Option<Vec<Key>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub read_options: Option<ReadOptions>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct LookupResponse {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub found: Option<Vec<EntityResult>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub missing: Option<Vec<EntityResult>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub deferred: Option<Vec<Key>>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ReadOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub transaction: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub read_consistency: Option<String>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct EntityResult {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub cursor: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub version: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub entity: Option<Entity>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Entity {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub properties: Option<HashMap<String, Value>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub key: Option<Key>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Key {
    pub path: Vec<PathElement>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub partition_id: Option<PartitionId>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct PathElement {
    pub kind: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct PartitionId {
    pub project_id: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub namespace_id: Option<String>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Value {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub entity_value: Option<Entity>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub timestamp_value: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub string_value: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub double_value: Option<f64>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub meaning: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub exclude_from_indexes: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub blob_value: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub key_value: Option<Key>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub boolean_value: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub integer_value: Option<i64>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub null_value: Option<String>,

    //#[serde(rename="geoPointValue")]
    //#[serde(skip_serializing_if = "Option::is_none")]
    //pub geo_point_value: Option<LatLng>,

    //#[serde(rename="arrayValue")]
    //#[serde(skip_serializing_if = "Option::is_none")]
    //pub array_value: Option<ArrayValue>,
}

impl<'a> Hub<'a> {
    //
    // api-level operations

    pub fn begin_transaction(&self) -> client::Result<String> {
        let uri = self.mk_uri("beginTransaction");
        let req = BeginTransactionRequest::default();
        self.post::<_, BeginTransactionResponse>(&uri, req, &[])
            .map(|r| r.transaction)
    }

    pub fn commit(&self, req: CommitRequest) -> client::Result<CommitResponse> {
        debug_assert!(!req.transaction.is_empty());
        let uri = self.mk_uri("commit");
        self.post(&uri, req, &[])
    }

    //
    // high-level operations

    pub fn insert_entity_auto_id(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        props: ValueMap,
    ) -> client::Result<String> {
        let key = self.mk_key(kind, Some(ns), ancestors, None, None);
        let res = self.insert(key, props)?;
        let mut results = res.mutation_results.expect("mutations to be valid");

        let mut key = results.remove(0).key.expect("key to be valid");
        Ok(key.path.pop().expect("path to be non-empty").id.expect(
            "id to be valid",
        ))
    }

    pub fn insert_entity_by_name(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        name: &str,
        props: ValueMap,
    ) -> client::Result<()> {
        let key = self.mk_key(kind, Some(ns), ancestors, Some(name), None);
        self.insert(key, props)?;
        Ok(())
    }

    fn insert(&self, key: Key, props: ValueMap) -> client::Result<CommitResponse> {
        let entity = Entity {
            key: Some(key),
            properties: Some(props),
        };

        let insert = Mutation {
            insert: Some(entity),
            ..Default::default()
        };

        let req = CommitRequest {
            transaction: self.begin_transaction()?,
            mutations: Some(vec![insert]),
            ..Default::default()
        };

        self.commit(req)
    }

    pub fn lookup_by_id(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        id: &str,
    ) -> client::Result<Option<ValueMap>> {
        let key = self.mk_key(kind, Some(ns), ancestors, None, Some(id));
        self.lookup_one(key)
    }

    pub fn lookup_by_name(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        name: &str,
    ) -> client::Result<Option<ValueMap>> {
        let key = self.mk_key(kind, Some(ns), ancestors, Some(name), None);
        self.lookup_one(key)
    }

    pub fn gql<B>(&self, ns: &str, q: &str, bindings: B) -> client::Result<RunQueryResponse>
    where
        B: IntoIterator<Item = (String, Value)>,
    {
        let query = GqlQuery {
            query_string: q.to_string(),
            allow_literals: false,
            named_bindings: bindings
                .into_iter()
                .map(|(k, v)| (k, GqlQueryParameter { value: v }))
                .collect(),
        };

        let req = RunQueryRequest {
            partition_id: PartitionId {
                project_id: self.project_id().to_string(),
                namespace_id: Some(ns.to_string()),
            },
            read_options: ReadOptions { ..Default::default() },
            gql_query: Some(query),
        };

        let uri = self.mk_uri("runQuery");
        self.post::<_, RunQueryResponse>(&uri, req, &[])
    }

    // Lookup a key using default read options:
    // https://cloud.google.com/datastore/docs/reference/rest/v1/ReadOptions
    fn lookup_one(&self, key: Key) -> client::Result<Option<ValueMap>> {
        let req = LookupRequest {
            keys: Some(vec![key]),
            read_options: None,
        };

        let uri = self.mk_uri("lookup");
        let res = self.post::<_, LookupResponse>(&uri, req, &[])?;

        Ok(
            res.found
                .and_then(|mut f| if f.len() != 1 {
                    None
                } else {
                    f.remove(0).entity
                })
                .and_then(|e| e.properties),
        )
    }

    pub fn update_by_id(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        id: &str,
        props: ValueMap,
    ) -> client::Result<()> {
        let key = self.mk_key(kind, Some(ns), ancestors, None, Some(id));

        let entity = Entity {
            key: Some(key),
            properties: Some(props),
        };

        let update = Mutation {
            update: Some(entity),
            ..Default::default()
        };

        let req = CommitRequest {
            transaction: self.begin_transaction()?,
            mutations: Some(vec![update]),
            ..Default::default()
        };

        self.commit(req).map(|_| ())
    }

    pub fn delete_by_id(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        id: &str,
    ) -> client::Result<()> {
        let key = self.mk_key(kind, Some(ns), ancestors, None, Some(id));

        let delete = Mutation {
            delete: Some(key),
            ..Default::default()
        };

        let req = CommitRequest {
            transaction: self.begin_transaction()?,
            mutations: Some(vec![delete]),
            ..Default::default()
        };

        self.commit(req).map(|_| ())
    }

    fn mk_uri(&self, action: &str) -> Uri {
        let path = format!(
            "{}/projects/{}:{}",
            DATASTORE_ROOT,
            self.project_id(),
            action
        );
        Uri::from_str(&path).expect("uri to be valid")
    }

    fn mk_key(
        &self,
        kind: &str,
        ns: Option<&str>,
        mut path: Vec<PathElement>,
        name: Option<&str>,
        id: Option<&str>,
    ) -> Key {
        let partition_id = PartitionId {
            project_id: self.project_id().to_string(),
            namespace_id: ns.map(|ns| ns.to_string()),
        };

        path.push(PathElement {
            kind: kind.to_string(),
            name: name.map(|name| name.to_string()),
            id: id.map(|id| id.to_string()),
        });

        Key {
            path: path,
            partition_id: Some(partition_id),
        }
    }
}
<commit_msg>pass down an optional txn<commit_after>use std::collections::HashMap;
use std::str::FromStr;

use hyper::Uri;

use client::{self, ApiClient};

static DATASTORE_ROOT: &str = "https://datastore.googleapis.com/v1";

pub struct DatastoreService {}
pub type Hub<'a> = client::Hub<'a, DatastoreService>;

pub type ValueMap = HashMap<String, Value>;

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct BeginTransactionRequest {}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct BeginTransactionResponse {
    pub transaction: String,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct CommitRequest {
    pub transaction: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub mode: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub mutations: Option<Vec<Mutation>>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct CommitResponse {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub mutation_results: Option<Vec<MutationResult>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub index_updates: Option<i32>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
struct RunQueryRequest {
    partition_id: PartitionId,
    read_options: ReadOptions,

    #[serde(skip_serializing_if = "Option::is_none")]
    gql_query: Option<GqlQuery>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
struct GqlQuery {
    query_string: String,
    allow_literals: bool,
    named_bindings: HashMap<String, GqlQueryParameter>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
struct GqlQueryParameter {
    value: Value,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RunQueryResponse {
    pub batch: QueryResultBatch,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct QueryResultBatch {
    pub entity_results: Option<Vec<EntityResult>>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Mutation {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub insert: Option<Entity>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub upsert: Option<Entity>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub update: Option<Entity>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub base_version: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub delete: Option<Key>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct MutationResult {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub version: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub conflict_detected: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub key: Option<Key>,
}

#[derive(Serialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct LookupRequest {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub keys: Option<Vec<Key>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub read_options: Option<ReadOptions>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct LookupResponse {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub found: Option<Vec<EntityResult>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub missing: Option<Vec<EntityResult>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub deferred: Option<Vec<Key>>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ReadOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub transaction: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub read_consistency: Option<String>,
}

#[derive(Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct EntityResult {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub cursor: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub version: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub entity: Option<Entity>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Entity {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub properties: Option<HashMap<String, Value>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub key: Option<Key>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Key {
    pub path: Vec<PathElement>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub partition_id: Option<PartitionId>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct PathElement {
    pub kind: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct PartitionId {
    pub project_id: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub namespace_id: Option<String>,
}

#[derive(Serialize, Deserialize, Default, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Value {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub entity_value: Option<Entity>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub timestamp_value: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub string_value: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub double_value: Option<f64>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub meaning: Option<i32>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub exclude_from_indexes: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub blob_value: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub key_value: Option<Key>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub boolean_value: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub integer_value: Option<i64>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub null_value: Option<String>,

    //#[serde(rename="geoPointValue")]
    //#[serde(skip_serializing_if = "Option::is_none")]
    //pub geo_point_value: Option<LatLng>,

    //#[serde(rename="arrayValue")]
    //#[serde(skip_serializing_if = "Option::is_none")]
    //pub array_value: Option<ArrayValue>,
}

impl<'a> Hub<'a> {
    //
    // api-level operations

    pub fn begin_transaction(&self) -> client::Result<String> {
        let uri = self.mk_uri("beginTransaction");
        let req = BeginTransactionRequest::default();
        self.post::<_, BeginTransactionResponse>(&uri, req, &[])
            .map(|r| r.transaction)
    }

    pub fn commit(&self, req: CommitRequest) -> client::Result<CommitResponse> {
        debug_assert!(!req.transaction.is_empty());
        let uri = self.mk_uri("commit");
        self.post(&uri, req, &[])
    }

    //
    // high-level operations

    pub fn insert_entity_auto_id(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        props: ValueMap,
    ) -> client::Result<String> {
        let key = self.mk_key(kind, Some(ns), ancestors, None, None);
        let res = self.insert(key, props)?;
        let mut results = res.mutation_results.expect("mutations to be valid");

        let mut key = results.remove(0).key.expect("key to be valid");
        Ok(key.path.pop().expect("path to be non-empty").id.expect(
            "id to be valid",
        ))
    }

    pub fn insert_entity_by_name(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        name: &str,
        props: ValueMap,
    ) -> client::Result<()> {
        let key = self.mk_key(kind, Some(ns), ancestors, Some(name), None);
        self.insert(key, props)?;
        Ok(())
    }

    fn insert(&self, key: Key, props: ValueMap) -> client::Result<CommitResponse> {
        let entity = Entity {
            key: Some(key),
            properties: Some(props),
        };

        let insert = Mutation {
            insert: Some(entity),
            ..Default::default()
        };

        let req = CommitRequest {
            transaction: self.begin_transaction()?,
            mutations: Some(vec![insert]),
            ..Default::default()
        };

        self.commit(req)
    }

    pub fn lookup_by_id(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        id: &str,
    ) -> client::Result<Option<ValueMap>> {
        let key = self.mk_key(kind, Some(ns), ancestors, None, Some(id));
        self.lookup_one(key)
    }

    pub fn lookup_by_name(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        name: &str,
    ) -> client::Result<Option<ValueMap>> {
        let key = self.mk_key(kind, Some(ns), ancestors, Some(name), None);
        self.lookup_one(key)
    }

    pub fn gql<B>(
        &self,
        ns: &str,
        q: &str,
        txn: Option<&str>,
        bindings: B,
    ) -> client::Result<RunQueryResponse>
    where
        B: IntoIterator<Item = (String, Value)>,
    {
        let query = GqlQuery {
            query_string: q.to_string(),
            allow_literals: false,
            named_bindings: bindings
                .into_iter()
                .map(|(k, v)| (k, GqlQueryParameter { value: v }))
                .collect(),
        };

        let req = RunQueryRequest {
            partition_id: PartitionId {
                project_id: self.project_id().to_string(),
                namespace_id: Some(ns.to_string()),
            },
            read_options: ReadOptions {
                transaction: txn.map(|t| t.to_string()),
                ..Default::default()
            },
            gql_query: Some(query),
        };

        let uri = self.mk_uri("runQuery");
        self.post::<_, RunQueryResponse>(&uri, req, &[])
    }

    // Lookup a key using default read options:
    // https://cloud.google.com/datastore/docs/reference/rest/v1/ReadOptions
    fn lookup_one(&self, key: Key) -> client::Result<Option<ValueMap>> {
        let req = LookupRequest {
            keys: Some(vec![key]),
            read_options: None,
        };

        let uri = self.mk_uri("lookup");
        let res = self.post::<_, LookupResponse>(&uri, req, &[])?;

        Ok(
            res.found
                .and_then(|mut f| if f.len() != 1 {
                    None
                } else {
                    f.remove(0).entity
                })
                .and_then(|e| e.properties),
        )
    }

    pub fn update_by_id(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        id: &str,
        props: ValueMap,
    ) -> client::Result<()> {
        let key = self.mk_key(kind, Some(ns), ancestors, None, Some(id));

        let entity = Entity {
            key: Some(key),
            properties: Some(props),
        };

        let update = Mutation {
            update: Some(entity),
            ..Default::default()
        };

        let req = CommitRequest {
            transaction: self.begin_transaction()?,
            mutations: Some(vec![update]),
            ..Default::default()
        };

        self.commit(req).map(|_| ())
    }

    pub fn delete_by_id(
        &self,
        kind: &str,
        ns: &str,
        ancestors: Vec<PathElement>,
        id: &str,
    ) -> client::Result<()> {
        let key = self.mk_key(kind, Some(ns), ancestors, None, Some(id));

        let delete = Mutation {
            delete: Some(key),
            ..Default::default()
        };

        let req = CommitRequest {
            transaction: self.begin_transaction()?,
            mutations: Some(vec![delete]),
            ..Default::default()
        };

        self.commit(req).map(|_| ())
    }

    fn mk_uri(&self, action: &str) -> Uri {
        let path = format!(
            "{}/projects/{}:{}",
            DATASTORE_ROOT,
            self.project_id(),
            action
        );
        Uri::from_str(&path).expect("uri to be valid")
    }

    fn mk_key(
        &self,
        kind: &str,
        ns: Option<&str>,
        mut path: Vec<PathElement>,
        name: Option<&str>,
        id: Option<&str>,
    ) -> Key {
        let partition_id = PartitionId {
            project_id: self.project_id().to_string(),
            namespace_id: ns.map(|ns| ns.to_string()),
        };

        path.push(PathElement {
            kind: kind.to_string(),
            name: name.map(|name| name.to_string()),
            id: id.map(|id| id.to_string()),
        });

        Key {
            path: path,
            partition_id: Some(partition_id),
        }
    }
}
<|endoftext|>


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

use super::*;
use punctuated::Punctuated;

ast_struct! {
    /// An enum variant.
    ///
    /// *This type is available if Syn is built with the `"derive"` or `"full"`
    /// feature.*
    pub struct Variant {
        /// Attributes tagged on the variant.
        pub attrs: Vec<Attribute>,

        /// Name of the variant.
        pub ident: Ident,

        /// Content stored in the variant.
        pub fields: Fields,

        /// Explicit discriminant: `Variant = 1`
        pub discriminant: Option<(Token![=], Expr)>,
    }
}

ast_enum_of_structs! {
    /// Data stored within an enum variant or struct.
    ///
    /// *This type is available if Syn is built with the `"derive"` or `"full"`
    /// feature.*
    ///
    /// # Syntax tree enum
    ///
    /// This type is a [syntax tree enum].
    ///
    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
    pub enum Fields {
        /// Named fields of a struct or struct variant such as `Point { x: f64,
        /// y: f64 }`.
        ///
        /// *This type is available if Syn is built with the `"derive"` or
        /// `"full"` feature.*
        pub Named(FieldsNamed {
            pub brace_token: token::Brace,
            pub named: Punctuated<Field, Token![,]>,
        }),

        /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
        ///
        /// *This type is available if Syn is built with the `"derive"` or
        /// `"full"` feature.*
        pub Unnamed(FieldsUnnamed {
            pub paren_token: token::Paren,
            pub unnamed: Punctuated<Field, Token![,]>,
        }),

        /// Unit struct or unit variant such as `None`.
        pub Unit,
    }
}

impl Fields {
    /// Get an iterator over the borrowed [`Field`] items in this object. This
    /// iterator can be used to iterate over a named or unnamed struct or
    /// variant's fields uniformly.
    ///
    /// [`Field`]: struct.Field.html
    pub fn iter(&self) -> punctuated::Iter<Field> {
        match *self {
            Fields::Unit => private::empty_punctuated_iter(),
            Fields::Named(ref f) => f.named.iter(),
            Fields::Unnamed(ref f) => f.unnamed.iter(),
        }
    }

    /// Get an iterator over the mutably borrowed [`Field`] items in this
    /// object. This iterator can be used to iterate over a named or unnamed
    /// struct or variant's fields uniformly.
    ///
    /// [`Field`]: struct.Field.html
    pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
        match *self {
            Fields::Unit => private::empty_punctuated_iter_mut(),
            Fields::Named(ref mut f) => f.named.iter_mut(),
            Fields::Unnamed(ref mut f) => f.unnamed.iter_mut(),
        }
    }
}

impl<'a> IntoIterator for &'a Fields {
    type Item = &'a Field;
    type IntoIter = punctuated::Iter<'a, Field>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a> IntoIterator for &'a mut Fields {
    type Item = &'a mut Field;
    type IntoIter = punctuated::IterMut<'a, Field>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

ast_struct! {
    /// A field of a struct or enum variant.
    ///
    /// *This type is available if Syn is built with the `"derive"` or `"full"`
    /// feature.*
    pub struct Field {
        /// Attributes tagged on the field.
        pub attrs: Vec<Attribute>,

        /// Visibility of the field.
        pub vis: Visibility,

        /// Name of the field, if any.
        ///
        /// Fields of tuple structs have no names.
        pub ident: Option<Ident>,

        pub colon_token: Option<Token![:]>,

        /// Type of the field.
        pub ty: Type,
    }
}

ast_enum_of_structs! {
    /// The visibility level of an item: inherited or `pub` or
    /// `pub(restricted)`.
    ///
    /// *This type is available if Syn is built with the `"derive"` or `"full"`
    /// feature.*
    ///
    /// # Syntax tree enum
    ///
    /// This type is a [syntax tree enum].
    ///
    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
    pub enum Visibility {
        /// A public visibility level: `pub`.
        ///
        /// *This type is available if Syn is built with the `"derive"` or
        /// `"full"` feature.*
        pub Public(VisPublic {
            pub pub_token: Token![pub],
        }),

        /// A crate-level visibility: `crate`.
        ///
        /// *This type is available if Syn is built with the `"derive"` or
        /// `"full"` feature.*
        pub Crate(VisCrate {
            pub crate_token: Token![crate],
        }),

        /// A visibility level restricted to some path: `pub(self)` or
        /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
        ///
        /// *This type is available if Syn is built with the `"derive"` or
        /// `"full"` feature.*
        pub Restricted(VisRestricted {
            pub pub_token: Token![pub],
            pub paren_token: token::Paren,
            pub in_token: Option<Token![in]>,
            pub path: Box<Path>,
        }),

        /// An inherited visibility, which usually means private.
        pub Inherited,
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;

    use ext::IdentExt;
    use parse::{Parse, ParseStream, Result};

    impl Parse for Variant {
        fn parse(input: ParseStream) -> Result<Self> {
            Ok(Variant {
                attrs: input.call(Attribute::parse_outer)?,
                ident: input.parse()?,
                fields: {
                    if input.peek(token::Brace) {
                        Fields::Named(input.parse()?)
                    } else if input.peek(token::Paren) {
                        Fields::Unnamed(input.parse()?)
                    } else {
                        Fields::Unit
                    }
                },
                discriminant: {
                    if input.peek(Token![=]) {
                        let eq_token: Token![=] = input.parse()?;
                        let discriminant: Expr = input.parse()?;
                        Some((eq_token, discriminant))
                    } else {
                        None
                    }
                },
            })
        }
    }

    impl Parse for FieldsNamed {
        fn parse(input: ParseStream) -> Result<Self> {
            let content;
            Ok(FieldsNamed {
                brace_token: braced!(content in input),
                named: content.parse_terminated(Field::parse_named)?,
            })
        }
    }

    impl Parse for FieldsUnnamed {
        fn parse(input: ParseStream) -> Result<Self> {
            let content;
            Ok(FieldsUnnamed {
                paren_token: parenthesized!(content in input),
                unnamed: content.parse_terminated(Field::parse_unnamed)?,
            })
        }
    }

    impl Field {
        fn parse_named(input: ParseStream) -> Result<Self> {
            Ok(Field {
                attrs: input.call(Attribute::parse_outer)?,
                vis: input.parse()?,
                ident: Some(input.parse()?),
                colon_token: Some(input.parse()?),
                ty: input.parse()?,
            })
        }

        fn parse_unnamed(input: ParseStream) -> Result<Self> {
            Ok(Field {
                attrs: input.call(Attribute::parse_outer)?,
                vis: input.parse()?,
                ident: None,
                colon_token: None,
                ty: input.parse()?,
            })
        }
    }

    impl Parse for Visibility {
        fn parse(input: ParseStream) -> Result<Self> {
            if input.peek(Token![pub]) {
                Self::parse_pub(input)
            } else if input.peek(Token![crate]) {
                Self::parse_crate(input)
            } else {
                Ok(Visibility::Inherited)
            }
        }
    }

    impl Visibility {
        fn parse_pub(input: ParseStream) -> Result<Self> {
            let pub_token = input.parse::<Token![pub]>()?;

            if input.peek(token::Paren) {
                let ahead = input.fork();
                let mut content;
                parenthesized!(content in ahead);

                if content.peek(Token![crate])
                    || content.peek(Token![self])
                    || content.peek(Token![super])
                {
                    return Ok(Visibility::Restricted(VisRestricted {
                        pub_token: pub_token,
                        paren_token: parenthesized!(content in input),
                        in_token: None,
                        path: Box::new(Path::from(content.call(Ident::parse_any)?)),
                    }));
                } else if content.peek(Token![in]) {
                    return Ok(Visibility::Restricted(VisRestricted {
                        pub_token: pub_token,
                        paren_token: parenthesized!(content in input),
                        in_token: Some(content.parse()?),
                        path: Box::new(content.call(Path::parse_mod_style)?),
                    }));
                }
            }

            Ok(Visibility::Public(VisPublic {
                pub_token: pub_token,
            }))
        }

        fn parse_crate(input: ParseStream) -> Result<Self> {
            if input.peek2(Token![::]) {
                Ok(Visibility::Inherited)
            } else {
                Ok(Visibility::Crate(VisCrate {
                    crate_token: input.parse()?,
                }))
            }
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;

    use proc_macro2::TokenStream;
    use quote::{ToTokens, TokenStreamExt};

    use print::TokensOrDefault;

    impl ToTokens for Variant {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.ident.to_tokens(tokens);
            self.fields.to_tokens(tokens);
            if let Some((ref eq_token, ref disc)) = self.discriminant {
                eq_token.to_tokens(tokens);
                disc.to_tokens(tokens);
            }
        }
    }

    impl ToTokens for FieldsNamed {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.brace_token.surround(tokens, |tokens| {
                self.named.to_tokens(tokens);
            });
        }
    }

    impl ToTokens for FieldsUnnamed {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.paren_token.surround(tokens, |tokens| {
                self.unnamed.to_tokens(tokens);
            });
        }
    }

    impl ToTokens for Field {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.vis.to_tokens(tokens);
            if let Some(ref ident) = self.ident {
                ident.to_tokens(tokens);
                TokensOrDefault(&self.colon_token).to_tokens(tokens);
            }
            self.ty.to_tokens(tokens);
        }
    }

    impl ToTokens for VisPublic {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.pub_token.to_tokens(tokens)
        }
    }

    impl ToTokens for VisCrate {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.crate_token.to_tokens(tokens);
        }
    }

    impl ToTokens for VisRestricted {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.pub_token.to_tokens(tokens);
            self.paren_token.surround(tokens, |tokens| {
                // TODO: If we have a path which is not "self" or "super" or
                // "crate", automatically add the "in" token.
                self.in_token.to_tokens(tokens);
                self.path.to_tokens(tokens);
            });
        }
    }
}
<commit_msg>Expose Field::parse_named and parse_unnamed<commit_after>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::*;
use punctuated::Punctuated;

ast_struct! {
    /// An enum variant.
    ///
    /// *This type is available if Syn is built with the `"derive"` or `"full"`
    /// feature.*
    pub struct Variant {
        /// Attributes tagged on the variant.
        pub attrs: Vec<Attribute>,

        /// Name of the variant.
        pub ident: Ident,

        /// Content stored in the variant.
        pub fields: Fields,

        /// Explicit discriminant: `Variant = 1`
        pub discriminant: Option<(Token![=], Expr)>,
    }
}

ast_enum_of_structs! {
    /// Data stored within an enum variant or struct.
    ///
    /// *This type is available if Syn is built with the `"derive"` or `"full"`
    /// feature.*
    ///
    /// # Syntax tree enum
    ///
    /// This type is a [syntax tree enum].
    ///
    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
    pub enum Fields {
        /// Named fields of a struct or struct variant such as `Point { x: f64,
        /// y: f64 }`.
        ///
        /// *This type is available if Syn is built with the `"derive"` or
        /// `"full"` feature.*
        pub Named(FieldsNamed {
            pub brace_token: token::Brace,
            pub named: Punctuated<Field, Token![,]>,
        }),

        /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
        ///
        /// *This type is available if Syn is built with the `"derive"` or
        /// `"full"` feature.*
        pub Unnamed(FieldsUnnamed {
            pub paren_token: token::Paren,
            pub unnamed: Punctuated<Field, Token![,]>,
        }),

        /// Unit struct or unit variant such as `None`.
        pub Unit,
    }
}

impl Fields {
    /// Get an iterator over the borrowed [`Field`] items in this object. This
    /// iterator can be used to iterate over a named or unnamed struct or
    /// variant's fields uniformly.
    ///
    /// [`Field`]: struct.Field.html
    pub fn iter(&self) -> punctuated::Iter<Field> {
        match *self {
            Fields::Unit => private::empty_punctuated_iter(),
            Fields::Named(ref f) => f.named.iter(),
            Fields::Unnamed(ref f) => f.unnamed.iter(),
        }
    }

    /// Get an iterator over the mutably borrowed [`Field`] items in this
    /// object. This iterator can be used to iterate over a named or unnamed
    /// struct or variant's fields uniformly.
    ///
    /// [`Field`]: struct.Field.html
    pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
        match *self {
            Fields::Unit => private::empty_punctuated_iter_mut(),
            Fields::Named(ref mut f) => f.named.iter_mut(),
            Fields::Unnamed(ref mut f) => f.unnamed.iter_mut(),
        }
    }
}

impl<'a> IntoIterator for &'a Fields {
    type Item = &'a Field;
    type IntoIter = punctuated::Iter<'a, Field>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a> IntoIterator for &'a mut Fields {
    type Item = &'a mut Field;
    type IntoIter = punctuated::IterMut<'a, Field>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

ast_struct! {
    /// A field of a struct or enum variant.
    ///
    /// *This type is available if Syn is built with the `"derive"` or `"full"`
    /// feature.*
    pub struct Field {
        /// Attributes tagged on the field.
        pub attrs: Vec<Attribute>,

        /// Visibility of the field.
        pub vis: Visibility,

        /// Name of the field, if any.
        ///
        /// Fields of tuple structs have no names.
        pub ident: Option<Ident>,

        pub colon_token: Option<Token![:]>,

        /// Type of the field.
        pub ty: Type,
    }
}

ast_enum_of_structs! {
    /// The visibility level of an item: inherited or `pub` or
    /// `pub(restricted)`.
    ///
    /// *This type is available if Syn is built with the `"derive"` or `"full"`
    /// feature.*
    ///
    /// # Syntax tree enum
    ///
    /// This type is a [syntax tree enum].
    ///
    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
    pub enum Visibility {
        /// A public visibility level: `pub`.
        ///
        /// *This type is available if Syn is built with the `"derive"` or
        /// `"full"` feature.*
        pub Public(VisPublic {
            pub pub_token: Token![pub],
        }),

        /// A crate-level visibility: `crate`.
        ///
        /// *This type is available if Syn is built with the `"derive"` or
        /// `"full"` feature.*
        pub Crate(VisCrate {
            pub crate_token: Token![crate],
        }),

        /// A visibility level restricted to some path: `pub(self)` or
        /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
        ///
        /// *This type is available if Syn is built with the `"derive"` or
        /// `"full"` feature.*
        pub Restricted(VisRestricted {
            pub pub_token: Token![pub],
            pub paren_token: token::Paren,
            pub in_token: Option<Token![in]>,
            pub path: Box<Path>,
        }),

        /// An inherited visibility, which usually means private.
        pub Inherited,
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;

    use ext::IdentExt;
    use parse::{Parse, ParseStream, Result};

    impl Parse for Variant {
        fn parse(input: ParseStream) -> Result<Self> {
            Ok(Variant {
                attrs: input.call(Attribute::parse_outer)?,
                ident: input.parse()?,
                fields: {
                    if input.peek(token::Brace) {
                        Fields::Named(input.parse()?)
                    } else if input.peek(token::Paren) {
                        Fields::Unnamed(input.parse()?)
                    } else {
                        Fields::Unit
                    }
                },
                discriminant: {
                    if input.peek(Token![=]) {
                        let eq_token: Token![=] = input.parse()?;
                        let discriminant: Expr = input.parse()?;
                        Some((eq_token, discriminant))
                    } else {
                        None
                    }
                },
            })
        }
    }

    impl Parse for FieldsNamed {
        fn parse(input: ParseStream) -> Result<Self> {
            let content;
            Ok(FieldsNamed {
                brace_token: braced!(content in input),
                named: content.parse_terminated(Field::parse_named)?,
            })
        }
    }

    impl Parse for FieldsUnnamed {
        fn parse(input: ParseStream) -> Result<Self> {
            let content;
            Ok(FieldsUnnamed {
                paren_token: parenthesized!(content in input),
                unnamed: content.parse_terminated(Field::parse_unnamed)?,
            })
        }
    }

    impl Field {
        /// Parses a named (braced struct) field.
        pub fn parse_named(input: ParseStream) -> Result<Self> {
            Ok(Field {
                attrs: input.call(Attribute::parse_outer)?,
                vis: input.parse()?,
                ident: Some(input.parse()?),
                colon_token: Some(input.parse()?),
                ty: input.parse()?,
            })
        }

        /// Parses an unnamed (tuple struct) field.
        pub fn parse_unnamed(input: ParseStream) -> Result<Self> {
            Ok(Field {
                attrs: input.call(Attribute::parse_outer)?,
                vis: input.parse()?,
                ident: None,
                colon_token: None,
                ty: input.parse()?,
            })
        }
    }

    impl Parse for Visibility {
        fn parse(input: ParseStream) -> Result<Self> {
            if input.peek(Token![pub]) {
                Self::parse_pub(input)
            } else if input.peek(Token![crate]) {
                Self::parse_crate(input)
            } else {
                Ok(Visibility::Inherited)
            }
        }
    }

    impl Visibility {
        fn parse_pub(input: ParseStream) -> Result<Self> {
            let pub_token = input.parse::<Token![pub]>()?;

            if input.peek(token::Paren) {
                let ahead = input.fork();
                let mut content;
                parenthesized!(content in ahead);

                if content.peek(Token![crate])
                    || content.peek(Token![self])
                    || content.peek(Token![super])
                {
                    return Ok(Visibility::Restricted(VisRestricted {
                        pub_token: pub_token,
                        paren_token: parenthesized!(content in input),
                        in_token: None,
                        path: Box::new(Path::from(content.call(Ident::parse_any)?)),
                    }));
                } else if content.peek(Token![in]) {
                    return Ok(Visibility::Restricted(VisRestricted {
                        pub_token: pub_token,
                        paren_token: parenthesized!(content in input),
                        in_token: Some(content.parse()?),
                        path: Box::new(content.call(Path::parse_mod_style)?),
                    }));
                }
            }

            Ok(Visibility::Public(VisPublic {
                pub_token: pub_token,
            }))
        }

        fn parse_crate(input: ParseStream) -> Result<Self> {
            if input.peek2(Token![::]) {
                Ok(Visibility::Inherited)
            } else {
                Ok(Visibility::Crate(VisCrate {
                    crate_token: input.parse()?,
                }))
            }
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;

    use proc_macro2::TokenStream;
    use quote::{ToTokens, TokenStreamExt};

    use print::TokensOrDefault;

    impl ToTokens for Variant {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.ident.to_tokens(tokens);
            self.fields.to_tokens(tokens);
            if let Some((ref eq_token, ref disc)) = self.discriminant {
                eq_token.to_tokens(tokens);
                disc.to_tokens(tokens);
            }
        }
    }

    impl ToTokens for FieldsNamed {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.brace_token.surround(tokens, |tokens| {
                self.named.to_tokens(tokens);
            });
        }
    }

    impl ToTokens for FieldsUnnamed {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.paren_token.surround(tokens, |tokens| {
                self.unnamed.to_tokens(tokens);
            });
        }
    }

    impl ToTokens for Field {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.vis.to_tokens(tokens);
            if let Some(ref ident) = self.ident {
                ident.to_tokens(tokens);
                TokensOrDefault(&self.colon_token).to_tokens(tokens);
            }
            self.ty.to_tokens(tokens);
        }
    }

    impl ToTokens for VisPublic {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.pub_token.to_tokens(tokens)
        }
    }

    impl ToTokens for VisCrate {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.crate_token.to_tokens(tokens);
        }
    }

    impl ToTokens for VisRestricted {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.pub_token.to_tokens(tokens);
            self.paren_token.surround(tokens, |tokens| {
                // TODO: If we have a path which is not "self" or "super" or
                // "crate", automatically add the "in" token.
                self.in_token.to_tokens(tokens);
                self.path.to_tokens(tokens);
            });
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2017, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use glib_sys;
use gobject_sys;
use libc;
use std::cmp;
use std::fmt;
use std::hash;
use translate::*;
use DateDay;
use DateMonth;
use DateWeekday;
use DateYear;
use Time;

glib_wrapper! {
    pub struct Date(Boxed<glib_sys::GDate>);

    match fn {
        copy => |ptr| gobject_sys::g_boxed_copy(glib_sys::g_date_get_type(), ptr as *const _) as *mut _,
        free => |ptr| glib_sys::g_date_free(ptr),
        get_type => || glib_sys::g_date_get_type(),
    }
}

unsafe impl Send for Date { }
unsafe impl Sync for Date { }

impl Date {
    pub fn new() -> Date {
        unsafe {
            from_glib_full(glib_sys::g_date_new())
        }
    }

    pub fn new_dmy(day: DateDay, month: DateMonth, year: DateYear) -> Date {
        unsafe {
            from_glib_full(glib_sys::g_date_new_dmy(day, month.to_glib(), year))
        }
    }

    pub fn new_julian(julian_day: u32) -> Date {
        unsafe {
            from_glib_full(glib_sys::g_date_new_julian(julian_day))
        }
    }

    pub fn add_days(&mut self, n_days: u32) {
        unsafe {
            glib_sys::g_date_add_days(self.to_glib_none_mut().0, n_days);
        }
    }

    pub fn add_months(&mut self, n_months: u32) {
        unsafe {
            glib_sys::g_date_add_months(self.to_glib_none_mut().0, n_months);
        }
    }

    pub fn add_years(&mut self, n_years: u32) {
        unsafe {
            glib_sys::g_date_add_years(self.to_glib_none_mut().0, n_years);
        }
    }

    pub fn clamp(&mut self, min_date: &Date, max_date: &Date) {
        unsafe {
            glib_sys::g_date_clamp(self.to_glib_none_mut().0, min_date.to_glib_none().0, max_date.to_glib_none().0);
        }
    }

    pub fn clear(&mut self, n_dates: u32) {
        unsafe {
            glib_sys::g_date_clear(self.to_glib_none_mut().0, n_dates);
        }
    }

    fn compare(&self, rhs: &Date) -> i32 {
        unsafe {
            glib_sys::g_date_compare(self.to_glib_none().0, rhs.to_glib_none().0)
        }
    }

    pub fn days_between(&self, date2: &Date) -> i32 {
        unsafe {
            glib_sys::g_date_days_between(self.to_glib_none().0, date2.to_glib_none().0)
        }
    }

    pub fn get_day(&self) -> DateDay {
        unsafe {
            glib_sys::g_date_get_day(self.to_glib_none().0)
        }
    }

    pub fn get_day_of_year(&self) -> u32 {
        unsafe {
            glib_sys::g_date_get_day_of_year(self.to_glib_none().0)
        }
    }

    pub fn get_iso8601_week_of_year(&self) -> u32 {
        unsafe {
            glib_sys::g_date_get_iso8601_week_of_year(self.to_glib_none().0)
        }
    }

    pub fn get_julian(&self) -> u32 {
        unsafe {
            glib_sys::g_date_get_julian(self.to_glib_none().0)
        }
    }

    pub fn get_monday_week_of_year(&self) -> u32 {
        unsafe {
            glib_sys::g_date_get_monday_week_of_year(self.to_glib_none().0)
        }
    }

    pub fn get_month(&self) -> DateMonth {
        unsafe {
            from_glib(glib_sys::g_date_get_month(self.to_glib_none().0))
        }
    }

    pub fn get_sunday_week_of_year(&self) -> u32 {
        unsafe {
            glib_sys::g_date_get_sunday_week_of_year(self.to_glib_none().0)
        }
    }

    pub fn get_weekday(&self) -> DateWeekday {
        unsafe {
            from_glib(glib_sys::g_date_get_weekday(self.to_glib_none().0))
        }
    }

    pub fn get_year(&self) -> DateYear {
        unsafe {
            glib_sys::g_date_get_year(self.to_glib_none().0)
        }
    }

    pub fn is_first_of_month(&self) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_is_first_of_month(self.to_glib_none().0))
        }
    }

    pub fn is_last_of_month(&self) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_is_last_of_month(self.to_glib_none().0))
        }
    }

    pub fn order(&mut self, date2: &mut Date) {
        unsafe {
            glib_sys::g_date_order(self.to_glib_none_mut().0, date2.to_glib_none_mut().0);
        }
    }

    pub fn set_day(&mut self, day: DateDay) {
        unsafe {
            glib_sys::g_date_set_day(self.to_glib_none_mut().0, day);
        }
    }

    pub fn set_dmy(&mut self, day: DateDay, month: DateMonth, y: DateYear) {
        unsafe {
            glib_sys::g_date_set_dmy(self.to_glib_none_mut().0, day, month.to_glib(), y);
        }
    }

    pub fn set_julian(&mut self, julian_date: u32) {
        unsafe {
            glib_sys::g_date_set_julian(self.to_glib_none_mut().0, julian_date);
        }
    }

    pub fn set_month(&mut self, month: DateMonth) {
        unsafe {
            glib_sys::g_date_set_month(self.to_glib_none_mut().0, month.to_glib());
        }
    }

    pub fn set_parse(&mut self, str: &str) {
        unsafe {
            glib_sys::g_date_set_parse(self.to_glib_none_mut().0, str.to_glib_none().0);
        }
    }

    pub fn set_time(&mut self, time_: Time) {
        unsafe {
            glib_sys::g_date_set_time(self.to_glib_none_mut().0, time_);
        }
    }

    pub fn set_time_t(&mut self, timet: libc::c_long) {
        unsafe {
            glib_sys::g_date_set_time_t(self.to_glib_none_mut().0, timet);
        }
    }

    //pub fn set_time_val(&mut self, timeval: /*Ignored*/&mut TimeVal) {
    //    unsafe { TODO: call glib_sys::g_date_set_time_val() }
    //}

    pub fn set_year(&mut self, year: DateYear) {
        unsafe {
            glib_sys::g_date_set_year(self.to_glib_none_mut().0, year);
        }
    }

    pub fn subtract_days(&mut self, n_days: u32) {
        unsafe {
            glib_sys::g_date_subtract_days(self.to_glib_none_mut().0, n_days);
        }
    }

    pub fn subtract_months(&mut self, n_months: u32) {
        unsafe {
            glib_sys::g_date_subtract_months(self.to_glib_none_mut().0, n_months);
        }
    }

    pub fn subtract_years(&mut self, n_years: u32) {
        unsafe {
            glib_sys::g_date_subtract_years(self.to_glib_none_mut().0, n_years);
        }
    }

    //pub fn to_struct_tm(&self, tm: /*Unimplemented*/Fundamental: Pointer) {
    //    unsafe { TODO: call glib_sys::g_date_to_struct_tm() }
    //}

    pub fn valid(&self) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_valid(self.to_glib_none().0))
        }
    }

    pub fn get_days_in_month(month: DateMonth, year: DateYear) -> u8 {
        unsafe {
            glib_sys::g_date_get_days_in_month(month.to_glib(), year)
        }
    }

    pub fn get_monday_weeks_in_year(year: DateYear) -> u8 {
        unsafe {
            glib_sys::g_date_get_monday_weeks_in_year(year)
        }
    }

    pub fn get_sunday_weeks_in_year(year: DateYear) -> u8 {
        unsafe {
            glib_sys::g_date_get_sunday_weeks_in_year(year)
        }
    }

    pub fn is_leap_year(year: DateYear) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_is_leap_year(year))
        }
    }

    pub fn strftime(s: &str, format: &str, date: &Date) -> usize {
        let slen = s.len() as usize;
        unsafe {
            glib_sys::g_date_strftime(s.to_glib_none().0, slen, format.to_glib_none().0, date.to_glib_none().0)
        }
    }

    pub fn valid_day(day: DateDay) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_valid_day(day))
        }
    }

    pub fn valid_dmy(day: DateDay, month: DateMonth, year: DateYear) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_valid_dmy(day, month.to_glib(), year))
        }
    }

    pub fn valid_julian(julian_date: u32) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_valid_julian(julian_date))
        }
    }

    pub fn valid_month(month: DateMonth) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_valid_month(month.to_glib()))
        }
    }

    pub fn valid_weekday(weekday: DateWeekday) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_valid_weekday(weekday.to_glib()))
        }
    }

    pub fn valid_year(year: DateYear) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_valid_year(year))
        }
    }
}

impl Default for Date {
    fn default() -> Self {
        Self::new()
    }
}

impl PartialEq for Date {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.compare(other) == 0
    }
}

impl Eq for Date {}

impl PartialOrd for Date {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
        self.compare(other).partial_cmp(&0)
    }
}

impl Ord for Date {
    #[inline]
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        self.compare(other).cmp(&0)
    }
}

impl fmt::Debug for Date {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Date")
            .field("year", &self.get_year())
            .field("month", &self.get_month())
            .field("day", &self.get_day())
            .finish()
    }
}

impl hash::Hash for Date {
    fn hash<H>(&self, state: &mut H) where H: hash::Hasher {
        self.get_year().hash(state);
        self.get_month().hash(state);
        self.get_day().hash(state);
    }
}
<commit_msg>Use new init/clear functions for glib::Date<commit_after>// Copyright 2017, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use glib_sys;
use gobject_sys;
use libc;
use std::cmp;
use std::fmt;
use std::hash;
use translate::*;
use DateDay;
use DateMonth;
use DateWeekday;
use DateYear;
use Time;

glib_wrapper! {
    pub struct Date(Boxed<glib_sys::GDate>);

    match fn {
        copy => |ptr| gobject_sys::g_boxed_copy(glib_sys::g_date_get_type(), ptr as *const _) as *mut _,
        free => |ptr| glib_sys::g_date_free(ptr),
        init => |_ptr| (),
        clear => |ptr| glib_sys::g_date_clear(ptr, 1),
        get_type => || glib_sys::g_date_get_type(),
    }
}

unsafe impl Send for Date { }
unsafe impl Sync for Date { }

impl Date {
    pub fn new() -> Date {
        unsafe {
            from_glib_full(glib_sys::g_date_new())
        }
    }

    pub fn new_dmy(day: DateDay, month: DateMonth, year: DateYear) -> Date {
        unsafe {
            from_glib_full(glib_sys::g_date_new_dmy(day, month.to_glib(), year))
        }
    }

    pub fn new_julian(julian_day: u32) -> Date {
        unsafe {
            from_glib_full(glib_sys::g_date_new_julian(julian_day))
        }
    }

    pub fn add_days(&mut self, n_days: u32) {
        unsafe {
            glib_sys::g_date_add_days(self.to_glib_none_mut().0, n_days);
        }
    }

    pub fn add_months(&mut self, n_months: u32) {
        unsafe {
            glib_sys::g_date_add_months(self.to_glib_none_mut().0, n_months);
        }
    }

    pub fn add_years(&mut self, n_years: u32) {
        unsafe {
            glib_sys::g_date_add_years(self.to_glib_none_mut().0, n_years);
        }
    }

    pub fn clamp(&mut self, min_date: &Date, max_date: &Date) {
        unsafe {
            glib_sys::g_date_clamp(self.to_glib_none_mut().0, min_date.to_glib_none().0, max_date.to_glib_none().0);
        }
    }

    pub fn clear(&mut self, n_dates: u32) {
        unsafe {
            glib_sys::g_date_clear(self.to_glib_none_mut().0, n_dates);
        }
    }

    fn compare(&self, rhs: &Date) -> i32 {
        unsafe {
            glib_sys::g_date_compare(self.to_glib_none().0, rhs.to_glib_none().0)
        }
    }

    pub fn days_between(&self, date2: &Date) -> i32 {
        unsafe {
            glib_sys::g_date_days_between(self.to_glib_none().0, date2.to_glib_none().0)
        }
    }

    pub fn get_day(&self) -> DateDay {
        unsafe {
            glib_sys::g_date_get_day(self.to_glib_none().0)
        }
    }

    pub fn get_day_of_year(&self) -> u32 {
        unsafe {
            glib_sys::g_date_get_day_of_year(self.to_glib_none().0)
        }
    }

    pub fn get_iso8601_week_of_year(&self) -> u32 {
        unsafe {
            glib_sys::g_date_get_iso8601_week_of_year(self.to_glib_none().0)
        }
    }

    pub fn get_julian(&self) -> u32 {
        unsafe {
            glib_sys::g_date_get_julian(self.to_glib_none().0)
        }
    }

    pub fn get_monday_week_of_year(&self) -> u32 {
        unsafe {
            glib_sys::g_date_get_monday_week_of_year(self.to_glib_none().0)
        }
    }

    pub fn get_month(&self) -> DateMonth {
        unsafe {
            from_glib(glib_sys::g_date_get_month(self.to_glib_none().0))
        }
    }

    pub fn get_sunday_week_of_year(&self) -> u32 {
        unsafe {
            glib_sys::g_date_get_sunday_week_of_year(self.to_glib_none().0)
        }
    }

    pub fn get_weekday(&self) -> DateWeekday {
        unsafe {
            from_glib(glib_sys::g_date_get_weekday(self.to_glib_none().0))
        }
    }

    pub fn get_year(&self) -> DateYear {
        unsafe {
            glib_sys::g_date_get_year(self.to_glib_none().0)
        }
    }

    pub fn is_first_of_month(&self) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_is_first_of_month(self.to_glib_none().0))
        }
    }

    pub fn is_last_of_month(&self) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_is_last_of_month(self.to_glib_none().0))
        }
    }

    pub fn order(&mut self, date2: &mut Date) {
        unsafe {
            glib_sys::g_date_order(self.to_glib_none_mut().0, date2.to_glib_none_mut().0);
        }
    }

    pub fn set_day(&mut self, day: DateDay) {
        unsafe {
            glib_sys::g_date_set_day(self.to_glib_none_mut().0, day);
        }
    }

    pub fn set_dmy(&mut self, day: DateDay, month: DateMonth, y: DateYear) {
        unsafe {
            glib_sys::g_date_set_dmy(self.to_glib_none_mut().0, day, month.to_glib(), y);
        }
    }

    pub fn set_julian(&mut self, julian_date: u32) {
        unsafe {
            glib_sys::g_date_set_julian(self.to_glib_none_mut().0, julian_date);
        }
    }

    pub fn set_month(&mut self, month: DateMonth) {
        unsafe {
            glib_sys::g_date_set_month(self.to_glib_none_mut().0, month.to_glib());
        }
    }

    pub fn set_parse(&mut self, str: &str) {
        unsafe {
            glib_sys::g_date_set_parse(self.to_glib_none_mut().0, str.to_glib_none().0);
        }
    }

    pub fn set_time(&mut self, time_: Time) {
        unsafe {
            glib_sys::g_date_set_time(self.to_glib_none_mut().0, time_);
        }
    }

    pub fn set_time_t(&mut self, timet: libc::c_long) {
        unsafe {
            glib_sys::g_date_set_time_t(self.to_glib_none_mut().0, timet);
        }
    }

    //pub fn set_time_val(&mut self, timeval: /*Ignored*/&mut TimeVal) {
    //    unsafe { TODO: call glib_sys::g_date_set_time_val() }
    //}

    pub fn set_year(&mut self, year: DateYear) {
        unsafe {
            glib_sys::g_date_set_year(self.to_glib_none_mut().0, year);
        }
    }

    pub fn subtract_days(&mut self, n_days: u32) {
        unsafe {
            glib_sys::g_date_subtract_days(self.to_glib_none_mut().0, n_days);
        }
    }

    pub fn subtract_months(&mut self, n_months: u32) {
        unsafe {
            glib_sys::g_date_subtract_months(self.to_glib_none_mut().0, n_months);
        }
    }

    pub fn subtract_years(&mut self, n_years: u32) {
        unsafe {
            glib_sys::g_date_subtract_years(self.to_glib_none_mut().0, n_years);
        }
    }

    //pub fn to_struct_tm(&self, tm: /*Unimplemented*/Fundamental: Pointer) {
    //    unsafe { TODO: call glib_sys::g_date_to_struct_tm() }
    //}

    pub fn valid(&self) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_valid(self.to_glib_none().0))
        }
    }

    pub fn get_days_in_month(month: DateMonth, year: DateYear) -> u8 {
        unsafe {
            glib_sys::g_date_get_days_in_month(month.to_glib(), year)
        }
    }

    pub fn get_monday_weeks_in_year(year: DateYear) -> u8 {
        unsafe {
            glib_sys::g_date_get_monday_weeks_in_year(year)
        }
    }

    pub fn get_sunday_weeks_in_year(year: DateYear) -> u8 {
        unsafe {
            glib_sys::g_date_get_sunday_weeks_in_year(year)
        }
    }

    pub fn is_leap_year(year: DateYear) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_is_leap_year(year))
        }
    }

    pub fn strftime(s: &str, format: &str, date: &Date) -> usize {
        let slen = s.len() as usize;
        unsafe {
            glib_sys::g_date_strftime(s.to_glib_none().0, slen, format.to_glib_none().0, date.to_glib_none().0)
        }
    }

    pub fn valid_day(day: DateDay) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_valid_day(day))
        }
    }

    pub fn valid_dmy(day: DateDay, month: DateMonth, year: DateYear) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_valid_dmy(day, month.to_glib(), year))
        }
    }

    pub fn valid_julian(julian_date: u32) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_valid_julian(julian_date))
        }
    }

    pub fn valid_month(month: DateMonth) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_valid_month(month.to_glib()))
        }
    }

    pub fn valid_weekday(weekday: DateWeekday) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_valid_weekday(weekday.to_glib()))
        }
    }

    pub fn valid_year(year: DateYear) -> bool {
        unsafe {
            from_glib(glib_sys::g_date_valid_year(year))
        }
    }
}

impl Default for Date {
    fn default() -> Self {
        Self::new()
    }
}

impl PartialEq for Date {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.compare(other) == 0
    }
}

impl Eq for Date {}

impl PartialOrd for Date {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
        self.compare(other).partial_cmp(&0)
    }
}

impl Ord for Date {
    #[inline]
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        self.compare(other).cmp(&0)
    }
}

impl fmt::Debug for Date {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Date")
            .field("year", &self.get_year())
            .field("month", &self.get_month())
            .field("day", &self.get_day())
            .finish()
    }
}

impl hash::Hash for Date {
    fn hash<H>(&self, state: &mut H) where H: hash::Hasher {
        self.get_year().hash(state);
        self.get_month().hash(state);
        self.get_day().hash(state);
    }
}
<|endoftext|>


<commit_before>use codespan::CodeMap;
use std::{fmt, io};
use termcolor::{Color, ColorSpec, WriteColor};

use {Diagnostic, LabelStyle};

struct Pad<T>(T, usize);

impl<T: fmt::Display> fmt::Display for Pad<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for _ in 0..(self.1) {
            self.0.fmt(f)?;
        }
        Ok(())
    }
}

pub fn emit<W>(mut writer: W, codemap: &CodeMap, diagnostic: &Diagnostic) -> io::Result<()>
where
    W: WriteColor,
{
    let supports_color = writer.supports_color();
    let line_location_color = ColorSpec::new()
        // Blue is really difficult to see on the standard windows command line
        .set_fg(Some(if cfg!(windows) { Color::Cyan } else { Color::Blue }))
        .clone();
    let diagnostic_color = ColorSpec::new()
        .set_fg(Some(diagnostic.severity.color()))
        .clone();

    writer.set_color(&diagnostic_color)?;
    write!(writer, "{}", diagnostic.severity)?;
    writer.reset()?;
    writeln!(writer, ": {}", diagnostic.message)?;
    for label in &diagnostic.labels {
        match codemap.find_file(label.span.start()) {
            None => if let Some(ref message) = label.message {
                writeln!(writer, "- {}", message)?
            },
            Some(file) => {
                let (line, column) = file.location(label.span.start()).expect("location");
                writeln!(
                    writer,
                    "- {file}:{line}:{column}",
                    file = file.name(),
                    line = line.number(),
                    column = column.number(),
                )?;

                let line_span = file.line_span(line).expect("line_span");

                let line_prefix = file.src_slice(line_span.with_end(label.span.start()))
                    .expect("line_prefix");
                let line_marked = file.src_slice(label.span).expect("line_marked");
                let line_suffix = file.src_slice(line_span.with_start(label.span.end()))
                    .expect("line_suffix")
                    .trim_right_matches(|ch: char| ch == '\r' || ch == '\n');

                let mark = match label.style {
                    LabelStyle::Primary => '^',
                    LabelStyle::Secondary => '-',
                };
                let label_color = match label.style {
                    LabelStyle::Primary => diagnostic_color.clone(),
                    LabelStyle::Secondary => ColorSpec::new()
                        .set_fg(Some(if cfg!(windows) {
                            Color::Cyan
                        } else {
                            Color::Blue
                        }))
                        .clone(),
                };

                writer.set_color(&line_location_color)?;
                let line_string = line.number().to_string();
                let line_location_prefix = format!("{} | ", Pad(' ', line_string.len()));
                write!(writer, "{} | ", line_string)?;
                writer.reset()?;

                write!(writer, "{}", line_prefix)?;
                writer.set_color(&label_color)?;
                write!(writer, "{}", line_marked)?;
                writer.reset()?;
                writeln!(writer, "{}", line_suffix)?;

                if !supports_color || label.message.is_some() {
                    writer.set_color(&line_location_color)?;
                    write!(writer, "{}", line_location_prefix)?;
                    writer.reset()?;

                    writer.set_color(&label_color)?;
                    write!(
                        writer,
                        "{}{}",
                        Pad(' ', line_prefix.len()),
                        Pad(mark, line_marked.len()),
                    )?;
                    writer.reset()?;

                    if label.message.is_none() {
                        writeln!(writer)?;
                    }
                }

                match label.message {
                    None => (),
                    Some(ref label) => {
                        writer.set_color(&label_color)?;
                        writeln!(writer, " {}", label)?;
                        writer.reset()?;
                    }
                }
            }
        }
    }
    Ok(())
}
<commit_msg>feat: Accentuate the main error message with bold and intense color<commit_after>use codespan::CodeMap;
use std::{fmt, io};
use termcolor::{Color, ColorSpec, WriteColor};

use {Diagnostic, LabelStyle};

struct Pad<T>(T, usize);

impl<T: fmt::Display> fmt::Display for Pad<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for _ in 0..(self.1) {
            self.0.fmt(f)?;
        }
        Ok(())
    }
}

pub fn emit<W>(mut writer: W, codemap: &CodeMap, diagnostic: &Diagnostic) -> io::Result<()>
where
    W: WriteColor,
{
    let supports_color = writer.supports_color();
    let line_location_color = ColorSpec::new()
        // Blue is really difficult to see on the standard windows command line
        .set_fg(Some(if cfg!(windows) { Color::Cyan } else { Color::Blue }))
        .clone();
    let diagnostic_color = ColorSpec::new()
        .set_fg(Some(diagnostic.severity.color()))
        .clone();

    let highlight_color = ColorSpec::new().set_bold(true).set_intense(true).clone();

    writer.set_color(&diagnostic_color)?;
    write!(writer, "{}", diagnostic.severity)?;
    writer.reset()?;
    write!(writer, ":")?;
    writer.set_color(&highlight_color)?;
    writeln!(writer, " {}", diagnostic.message)?;
    writer.reset()?;

    for label in &diagnostic.labels {
        match codemap.find_file(label.span.start()) {
            None => if let Some(ref message) = label.message {
                writeln!(writer, "- {}", message)?
            },
            Some(file) => {
                let (line, column) = file.location(label.span.start()).expect("location");
                writeln!(
                    writer,
                    "- {file}:{line}:{column}",
                    file = file.name(),
                    line = line.number(),
                    column = column.number(),
                )?;

                let line_span = file.line_span(line).expect("line_span");

                let line_prefix = file.src_slice(line_span.with_end(label.span.start()))
                    .expect("line_prefix");
                let line_marked = file.src_slice(label.span).expect("line_marked");
                let line_suffix = file.src_slice(line_span.with_start(label.span.end()))
                    .expect("line_suffix")
                    .trim_right_matches(|ch: char| ch == '\r' || ch == '\n');

                let mark = match label.style {
                    LabelStyle::Primary => '^',
                    LabelStyle::Secondary => '-',
                };
                let label_color = match label.style {
                    LabelStyle::Primary => diagnostic_color.clone(),
                    LabelStyle::Secondary => ColorSpec::new()
                        .set_fg(Some(if cfg!(windows) {
                            Color::Cyan
                        } else {
                            Color::Blue
                        }))
                        .clone(),
                };

                writer.set_color(&line_location_color)?;
                let line_string = line.number().to_string();
                let line_location_prefix = format!("{} | ", Pad(' ', line_string.len()));
                write!(writer, "{} | ", line_string)?;
                writer.reset()?;

                write!(writer, "{}", line_prefix)?;
                writer.set_color(&label_color)?;
                write!(writer, "{}", line_marked)?;
                writer.reset()?;
                writeln!(writer, "{}", line_suffix)?;

                if !supports_color || label.message.is_some() {
                    writer.set_color(&line_location_color)?;
                    write!(writer, "{}", line_location_prefix)?;
                    writer.reset()?;

                    writer.set_color(&label_color)?;
                    write!(
                        writer,
                        "{}{}",
                        Pad(' ', line_prefix.len()),
                        Pad(mark, line_marked.len()),
                    )?;
                    writer.reset()?;

                    if label.message.is_none() {
                        writeln!(writer)?;
                    }
                }

                match label.message {
                    None => (),
                    Some(ref label) => {
                        writer.set_color(&label_color)?;
                        writeln!(writer, " {}", label)?;
                        writer.reset()?;
                    }
                }
            }
        }
    }
    Ok(())
}
<|endoftext|>