<commit_before>use hyper::{Client, Method, Error, StatusCode};
use hyper::header::{UserAgent};
use hyper::client::{Request, FutureResponse};
use hyper_tls::HttpsConnector;
use futures::{Future, Stream};
use futures::future;
use serde_json;
use slog::*;
use serde::Deserialize;

use utils::parse_url_from_str;
use models::*;
use endpoint::HnNewsEndpoint;
use app::AppDomain;

pub fn get_top_story_ids(app_domain: &mut AppDomain) -> Result<HnTopStories, Error> {
    let logger = &app_domain.logger; // These need to be here as otherwise it'll cause mutable<>immutable borrow error
    let endpoint = &app_domain.endpoint;
    let client = &app_domain.client;
    let work = request_top_story_ids(&client, &endpoint)
        .and_then(|res| {
            log_response_status(&logger, &endpoint.get_top_stories_path(), &res.status());
            res.body()
                .fold(Vec::new(), |mut v, chunk| {
                    v.extend(&chunk[..]);
                    future::ok::<_, Error>(v)
                })
        })
        .map(|chunks| deserialize::<HnTopStories>(chunks));
    let result = app_domain.core.run(work);
    result
}

fn deserialize<T: Deserialize>(chunks: Vec<u8>) -> T {
    let s = String::from_utf8(chunks).unwrap();
    let deserialized: T = serde_json::from_str(&s).unwrap();
    deserialized
}

///
/// Gets HnItem wrapped in Result
///
pub fn get_item_by_id(item: &str, app_domain: &mut AppDomain) -> Result<HnItem, Error> {
    // note kids in item are comments, parts not sure what it is
    let logger = &app_domain.logger; // These need to be here as otherwise it'll cause mutable<>immutable borrow error
    let endpoint = &app_domain.endpoint;
    let client = &app_domain.client;
    let work = request_item(&item, &client, &endpoint)
        .and_then(|res| {
            log_response_status(&logger, &endpoint.get_item_path(&item), &res.status());
            res.body()
                .fold(Vec::new(), |mut v, chunk| {
                    v.extend(&chunk[..]);
                    future::ok::<_, Error>(v)
                })
        })
        .map(|chunks| deserialize::<HnItem>(chunks));
    let result = app_domain.core.run(work);
    result
}

fn get_comments_for_item(app_domain: &mut AppDomain, item: &HnItem) -> Option<Vec<HnItem>> {
    match item.kids {
        Some(ref kids) => {
            let core = &mut app_domain.core;
            let logger = &mut app_domain.logger; // These need to be mutable as otherwise it'll cause mutable<>immutable borrow error
            let endpoint = &mut app_domain.endpoint;
            let client = &mut app_domain.client;
            let comments: &Vec<i32> = &kids;
            let raw_items = comments.iter()
                .map(|item_id| (item_id.to_string(), request_item(&item_id.to_string(), &client, &endpoint)))
                .map(|(item_id, request_work)| {
                    // Todo: add some logging for item_id
                    let subtask = request_work
                    .and_then(|response| {
                        response.body()
                            .fold(Vec::new(), |mut v, chunk| {
                                v.extend(&chunk[..]);
                                future::ok::<_, Error>(v)
                            })
                    });
                    core.run(subtask).unwrap()
                })
                .collect::<Vec<Vec<_>>>();
            let items = raw_items.into_iter().map(|chunks| deserialize::<HnItem>(chunks)).collect();
            Some(items)
        }
        None => None,
    }
}

fn log_response_status(logger: &Logger, url: &str, status: &StatusCode) {
    info!(logger,
          format!("Request to {} finished with status {}", url, status));
}

fn request_top_story_ids(client: &Client<HttpsConnector>,
                         endpoints: &HnNewsEndpoint)
                         -> FutureResponse {
    let url = parse_url_from_str(&endpoints.get_top_stories_path());
    let mut request = Request::new(Method::Get, url);
    common_headers(&mut request);
    client.request(request)
}
fn request_item(item: &str,
                client: &Client<HttpsConnector>,
                endpoints: &HnNewsEndpoint)
                -> FutureResponse {
    let url = parse_url_from_str(&endpoints.get_item_path(item));
    let mut request = Request::new(Method::Get, url);
    common_headers(&mut request);
    client.request(request)
}

fn common_headers(req: &mut Request) {
    req.headers_mut().set(UserAgent::new("rs-hackernews-cli"));
}

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

    #[test]
    fn request_item_test() {
        let mut app_domain = create_app_domain();
        let s = String::from("8000");
        let response = app_domain.core.run(request_item(&s, &app_domain.client, &app_domain.endpoint)).unwrap();
        assert_eq!(StatusCode::Ok, response.status());
    }
    #[test]
    fn request_top_stories_test() {
        let mut app_domain = create_app_domain();
        let response = app_domain.core.run(request_top_story_ids(&app_domain.client, &app_domain.endpoint)).unwrap();
        assert_eq!(StatusCode::Ok, response.status());
    }

    #[test]
    fn get_item_by_id_test() {
        let mut app_domain = create_app_domain();
        let s = String::from("126809");
        let hnitem: HnItem = get_item_by_id(&s, &mut app_domain).unwrap();
        assert!(hnitem.score.unwrap() != 0);
        assert!(hnitem.id != 0);
        assert!(!hnitem.type_str.is_empty());
        assert!(!hnitem.title.unwrap().is_empty());
        assert_eq!(126809, hnitem.id);
    }
    #[test]
    fn get_top_stories_test() {
        let mut app_domain = create_app_domain();
        let top_stories: HnTopStories = get_top_story_ids(&mut app_domain).unwrap();
        assert!(top_stories.values.len() != 0);
    }
    #[test]
    fn get_comments_test() {
        let mut app_domain = create_app_domain();
        let s = String::from("14114235");
        let hnitem: HnItem = get_item_by_id(&s, &mut app_domain).unwrap();
        let comments: Vec<HnItem> = get_comments_for_item(&mut app_domain, &hnitem).unwrap();
        assert!(comments.len() != 0);
    }
}
<commit_msg>Added some logging for comment retrieval<commit_after>use hyper::{Client, Method, Error, StatusCode};
use hyper::header::{UserAgent};
use hyper::client::{Request, FutureResponse};
use hyper_tls::HttpsConnector;
use futures::{Future, Stream};
use futures::future;
use serde_json;
use slog::*;
use serde::Deserialize;

use utils::parse_url_from_str;
use models::*;
use endpoint::HnNewsEndpoint;
use app::AppDomain;

pub fn get_top_story_ids(app_domain: &mut AppDomain) -> Result<HnTopStories, Error> {
    let logger = &app_domain.logger; // These need to be here as otherwise it'll cause mutable<>immutable borrow error
    let endpoint = &app_domain.endpoint;
    let client = &app_domain.client;
    let work = request_top_story_ids(&client, &endpoint)
        .and_then(|res| {
            log_response_status(&logger, &endpoint.get_top_stories_path(), &res.status());
            res.body()
                .fold(Vec::new(), |mut v, chunk| {
                    v.extend(&chunk[..]);
                    future::ok::<_, Error>(v)
                })
        })
        .map(|chunks| deserialize::<HnTopStories>(chunks));
    let result = app_domain.core.run(work);
    result
}

fn deserialize<T: Deserialize>(chunks: Vec<u8>) -> T {
    let s = String::from_utf8(chunks).unwrap();
    let deserialized: T = serde_json::from_str(&s).unwrap();
    deserialized
}

///
/// Gets HnItem wrapped in Result
///
pub fn get_item_by_id(item: &str, app_domain: &mut AppDomain) -> Result<HnItem, Error> {
    // note kids in item are comments, parts not sure what it is
    let logger = &app_domain.logger; // These need to be here as otherwise it'll cause mutable<>immutable borrow error
    let endpoint = &app_domain.endpoint;
    let client = &app_domain.client;
    let work = request_item(&item, &client, &endpoint)
        .and_then(|res| {
            log_response_status(&logger, &endpoint.get_item_path(&item), &res.status());
            res.body()
                .fold(Vec::new(), |mut v, chunk| {
                    v.extend(&chunk[..]);
                    future::ok::<_, Error>(v)
                })
        })
        .map(|chunks| deserialize::<HnItem>(chunks));
    let result = app_domain.core.run(work);
    result
}

fn get_comments_for_item(app_domain: &mut AppDomain, item: &HnItem) -> Option<Vec<HnItem>> {
    match item.kids {
        Some(ref kids) => {
            let core = &mut app_domain.core;
            let logger = &mut app_domain.logger; // These need to be mutable as otherwise it'll cause mutable<>immutable borrow error
            let endpoint = &mut app_domain.endpoint;
            let client = &mut app_domain.client;
            let comments: &Vec<i32> = &kids;
            info!(&logger, format!("Retrieving comments for {} with {} comments", &item.id, kids.len()));
            let raw_items = comments.iter()
                .map(|item_id| (item_id.to_string(), request_item(&item_id.to_string(), &client, &endpoint)))
                .map(|(item_id, request_work)| {
                    let subtask = request_work
                    .and_then(|response| {
                        response.body()
                            .fold(Vec::new(), |mut v, chunk| {
                                v.extend(&chunk[..]);
                                future::ok::<_, Error>(v)
                            })
                    });
                    core.run(subtask).unwrap()
                })
                .collect::<Vec<Vec<_>>>();
            let items = raw_items.into_iter().map(|chunks| deserialize::<HnItem>(chunks)).collect();
            Some(items)
        }
        None => None,
    }
}

fn log_response_status(logger: &Logger, url: &str, status: &StatusCode) {
    info!(logger,
          format!("Request to {} finished with status {}", url, status));
}

fn request_top_story_ids(client: &Client<HttpsConnector>,
                         endpoints: &HnNewsEndpoint)
                         -> FutureResponse {
    let url = parse_url_from_str(&endpoints.get_top_stories_path());
    let mut request = Request::new(Method::Get, url);
    common_headers(&mut request);
    client.request(request)
}
fn request_item(item: &str,
                client: &Client<HttpsConnector>,
                endpoints: &HnNewsEndpoint)
                -> FutureResponse {
    let url = parse_url_from_str(&endpoints.get_item_path(item));
    let mut request = Request::new(Method::Get, url);
    common_headers(&mut request);
    client.request(request)
}

fn common_headers(req: &mut Request) {
    req.headers_mut().set(UserAgent::new("rs-hackernews-cli"));
}

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

    #[test]
    fn request_item_test() {
        let mut app_domain = create_app_domain();
        let s = String::from("8000");
        let response = app_domain.core.run(request_item(&s, &app_domain.client, &app_domain.endpoint)).unwrap();
        assert_eq!(StatusCode::Ok, response.status());
    }
    #[test]
    fn request_top_stories_test() {
        let mut app_domain = create_app_domain();
        let response = app_domain.core.run(request_top_story_ids(&app_domain.client, &app_domain.endpoint)).unwrap();
        assert_eq!(StatusCode::Ok, response.status());
    }

    #[test]
    fn get_item_by_id_test() {
        let mut app_domain = create_app_domain();
        let s = String::from("126809");
        let hnitem: HnItem = get_item_by_id(&s, &mut app_domain).unwrap();
        assert!(hnitem.score.unwrap() != 0);
        assert!(hnitem.id != 0);
        assert!(!hnitem.type_str.is_empty());
        assert!(!hnitem.title.unwrap().is_empty());
        assert_eq!(126809, hnitem.id);
    }
    #[test]
    fn get_top_stories_test() {
        let mut app_domain = create_app_domain();
        let top_stories: HnTopStories = get_top_story_ids(&mut app_domain).unwrap();
        assert!(top_stories.values.len() != 0);
    }
    #[test]
    fn get_comments_test() {
        let mut app_domain = create_app_domain();
        let s = String::from("14114235");
        let hnitem: HnItem = get_item_by_id(&s, &mut app_domain).unwrap();
        let comments: Vec<HnItem> = get_comments_for_item(&mut app_domain, &hnitem).unwrap();
        assert!(comments.len() != 0);
    }
}
<|endoftext|>


<commit_before>#![feature(core_intrinsics)]
use std::fs::File;
use std::io::{BufRead, BufReader};

use std::intrinsics::unlikely;

const VALUE: [u64; 256] = {
    let mut array = [0u64; 256];
    array[b'A' as usize] = 1;
    array[b'T' as usize] = 1;
    array[b'G' as usize] = 1 << 32;
    array[b'C' as usize] = 1 << 32;
    array
};

const CHUNKSIZE: usize = 16;

fn main() {
    let filename = "chry_multiplied.fa";

    let file = File::open(filename).unwrap();
    let mut reader = BufReader::new(file);

    let mut totals = 0u64;
    let mut line = Vec::with_capacity(100);
    loop {
        if unlikely(reader.read_until(b'\n', &mut line).expect("error reading") == 0) {
            break;
        }

        if unlikely(line[0] == b'>') {
            line.clear();
            continue;
        }
        let mut chunker = line.chunks_exact(CHUNKSIZE);
        while let Some(chars) = chunker.next() {
            totals += (0..CHUNKSIZE)
                .into_iter()
                .map(|c| chars[c])
                .map(|b| VALUE[b as usize])
                .sum::<u64>();
        }
        for c in chunker.remainder() {
            totals += VALUE[*c as usize];
        }
        line.clear();
    }
    let at = totals & 0xFFFFFFFF;
    let gc = totals >> 32;
    let gc_ratio: f64 = gc as f64 / (gc as f64 + at as f64);
    println!("GC ratio (gc/(gc+at)): {}", gc_ratio);
}
<commit_msg>Faster vectorized loop<commit_after>#![feature(core_intrinsics)]
use std::fs::File;
use std::io::{BufRead, BufReader};

use std::intrinsics::unlikely;

fn main() {
    let filename = "chry_multiplied.fa";

    let file = File::open(filename).unwrap();
    let mut reader = BufReader::new(file);

    let mut line = Vec::with_capacity(100);
    let mut at = 0;
    let mut gc = 0;
    loop {
        if unlikely(reader.read_until(b'\n', &mut line).expect("error reading") == 0) {
            break;
        }

        if unlikely(line[0] == b'>') {
            line.clear();
            continue;
        }

        // G/C & 10 == 2
        // A/T & 10 == 0
        // N & 10 == 10
        for c in line.iter() {
            gc += (*c & 10 == 2) as u32;
            at += (*c & 10 == 0) as u32;
        }
        line.clear();
    }

    let gc_ratio: f64 = gc as f64 / (gc as f64 + at as f64);
    println!("GC ratio (gc/(gc+at)): {}", gc_ratio);
}
<|endoftext|>


<commit_before>macro_rules! component {
    ($name:ident : $inner:ident { $($key:ident : $ty:ty = $value:expr,)* }) => {
        #[derive(Clone)]
        pub struct $name(::std::sync::Arc<($crate::session::SessionWeak, ::std::sync::Mutex<$inner>)>);
        impl $name {
            #[allow(dead_code)]
            pub fn new(session: $crate::session::SessionWeak) -> $name {
                debug!(target:"librespot::component", "new {}", stringify!($name));

                $name(::std::sync::Arc::new((session, ::std::sync::Mutex::new($inner {
                    $($key : $value,)*
                }))))
            }

            #[allow(dead_code)]
            fn lock<F: FnOnce(&mut $inner) -> R, R>(&self, f: F) -> R {
                let mut inner = (self.0).1.lock().expect("Mutex poisoned");
                f(&mut inner)
            }

            #[allow(dead_code)]
            fn session(&self) -> $crate::session::Session {
                (self.0).0.upgrade()
            }
        }

        struct $inner {
            $($key : $ty,)*
        }

        impl Drop for $inner {
            fn drop(&mut self) {
                debug!(target:"librespot::component", "drop {}", stringify!($name));
            }
        }
    }
}

use std::cell::UnsafeCell;
use std::sync::Mutex;

pub struct Lazy<T>(Mutex<bool>, UnsafeCell<Option<T>>);
unsafe impl<T: Sync> Sync for Lazy<T> {}
unsafe impl<T: Send> Send for Lazy<T> {}

#[cfg_attr(feature = "cargo-clippy", allow(mutex_atomic))]
impl<T> Lazy<T> {
    pub fn new() -> Lazy<T> {
        Lazy(Mutex::new(false), UnsafeCell::new(None))
    }

    pub fn get<F: FnOnce() -> T>(&self, f: F) -> &T {
        let mut inner = self.0.lock().unwrap();
        if !*inner {
            unsafe {
                *self.1.get() = Some(f());
            }
            *inner = true;
        }

        unsafe { &*self.1.get() }.as_ref().unwrap()
    }
}
<commit_msg>core API: Lazy<commit_after>macro_rules! component {
    ($name:ident : $inner:ident { $($key:ident : $ty:ty = $value:expr,)* }) => {
        #[derive(Clone)]
        pub struct $name(::std::sync::Arc<($crate::session::SessionWeak, ::std::sync::Mutex<$inner>)>);
        impl $name {
            #[allow(dead_code)]
            pub fn new(session: $crate::session::SessionWeak) -> $name {
                debug!(target:"librespot::component", "new {}", stringify!($name));

                $name(::std::sync::Arc::new((session, ::std::sync::Mutex::new($inner {
                    $($key : $value,)*
                }))))
            }

            #[allow(dead_code)]
            fn lock<F: FnOnce(&mut $inner) -> R, R>(&self, f: F) -> R {
                let mut inner = (self.0).1.lock().expect("Mutex poisoned");
                f(&mut inner)
            }

            #[allow(dead_code)]
            fn session(&self) -> $crate::session::Session {
                (self.0).0.upgrade()
            }
        }

        struct $inner {
            $($key : $ty,)*
        }

        impl Drop for $inner {
            fn drop(&mut self) {
                debug!(target:"librespot::component", "drop {}", stringify!($name));
            }
        }
    }
}

use std::cell::UnsafeCell;
use std::sync::Mutex;

pub(crate) struct Lazy<T>(Mutex<bool>, UnsafeCell<Option<T>>);
unsafe impl<T: Sync> Sync for Lazy<T> {}
unsafe impl<T: Send> Send for Lazy<T> {}

#[cfg_attr(feature = "cargo-clippy", allow(mutex_atomic))]
impl<T> Lazy<T> {
    pub(crate) fn new() -> Lazy<T> {
        Lazy(Mutex::new(false), UnsafeCell::new(None))
    }

    pub(crate) fn get<F: FnOnce() -> T>(&self, f: F) -> &T {
        let mut inner = self.0.lock().unwrap();
        if !*inner {
            unsafe {
                *self.1.get() = Some(f());
            }
            *inner = true;
        }

        unsafe { &*self.1.get() }.as_ref().unwrap()
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate columnar;
#[macro_use] extern crate columnar_derive;

#[derive(Columnar, Debug, Default)]
struct Data {
    id: usize,
    val: f64,
    dummy: [usize; 30],
}

#[bench]
fn data_columnar(b: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: 15., ..Data::default()});
    }
    let mut dc = DataColumnar::with_capacity(size);
    dc.extend(a);
    b.iter(|| {
        for mut e in dc.iter_mut() {
            *e.id *= 2;
        }
    })
}

#[bench]
fn data_columnar_add_assign(bench: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    let mut b = Vec::with_capacity(size);
    let mut r = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: i as f64 * 0.6, ..Data::default()});
        b.push(Data { id: i + size, val: size as f64 + i as f64 * 0.6, ..Data::default()});
        r.push(Data { id: 0, val: 1., ..Data::default()});
    }
    let mut ca = DataColumnar::with_capacity(size);
    let mut cb = DataColumnar::with_capacity(size);
    let mut cr = DataColumnar::with_capacity(size);
    ca.extend(a);
    cb.extend(b);
    test::black_box(r.first().unwrap().dummy);
    cr.extend(r);
    bench.iter(|| {
        let zip: ::std::iter::Zip<_, _> = ca.iter().zip(cb.iter()).zip(cr.iter_mut());
        for ((ea, eb), mut er) in zip {
            *er.val /= ea.val + eb.val;
        };
    })
}

#[bench]
fn data_row_add_assign(bench: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    let mut b = Vec::with_capacity(size);
    let mut r = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: i as f64 * 0.6, ..Data::default()});
        b.push(Data { id: i + size, val: size as f64 + i as f64 * 0.6, ..Data::default()});
        r.push(Data { id: 0, val: 1., ..Data::default()});
    }
    test::black_box(r.first().unwrap().dummy);
    bench.iter(|| {
        let zip: ::std::iter::Zip<_, _> = a.iter().zip(b.iter()).zip(r.iter_mut());
        for ((ea, eb), mut er) in zip {
            er.val /= ea.val + eb.val;
        };
    })
}

#[bench]
fn data_row(b: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: 15., ..Data::default()});
    }
    b.iter(|| {
        for mut e in a.iter_mut() {
            e.id *= 2;
        }
    })
}
<commit_msg>benches: Print throughput<commit_after>#![feature(test)]

extern crate test;
extern crate columnar;
#[macro_use] extern crate columnar_derive;

use std::mem::size_of;

#[derive(Columnar, Debug, Default)]
struct Data {
    id: usize,
    val: f64,
    dummy: [usize; 30],
}

#[bench]
fn data_columnar(b: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: 15., ..Data::default()});
    }
    let mut dc = DataColumnar::with_capacity(size);
    dc.extend(a);
    b.bytes = (size_of::<usize>() * size) as u64;
    b.iter(|| {
        for mut e in dc.iter_mut() {
            *e.id *= 2;
        }
    })
}

#[bench]
fn data_columnar_add_assign(bench: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    let mut b = Vec::with_capacity(size);
    let mut r = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: i as f64 * 0.6, ..Data::default()});
        b.push(Data { id: i + size, val: size as f64 + i as f64 * 0.6, ..Data::default()});
        r.push(Data { id: 0, val: 1., ..Data::default()});
    }
    let mut ca = DataColumnar::with_capacity(size);
    let mut cb = DataColumnar::with_capacity(size);
    let mut cr = DataColumnar::with_capacity(size);
    ca.extend(a);
    cb.extend(b);
    test::black_box(r.first().unwrap().dummy);
    cr.extend(r);
    bench.bytes = (size_of::<f64>() * size * 3) as u64;
    bench.iter(|| {
        let zip: ::std::iter::Zip<_, _> = ca.iter().zip(cb.iter()).zip(cr.iter_mut());
        for ((ea, eb), mut er) in zip {
            *er.val /= ea.val + eb.val;
        };
    })
}

#[bench]
fn data_row_add_assign(bench: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    let mut b = Vec::with_capacity(size);
    let mut r = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: i as f64 * 0.6, ..Data::default()});
        b.push(Data { id: i + size, val: size as f64 + i as f64 * 0.6, ..Data::default()});
        r.push(Data { id: 0, val: 1., ..Data::default()});
    }
    test::black_box(r.first().unwrap().dummy);
    bench.bytes = (size_of::<f64>() * size * 3) as u64;
    bench.iter(|| {
        let zip: ::std::iter::Zip<_, _> = a.iter().zip(b.iter()).zip(r.iter_mut());
        for ((ea, eb), mut er) in zip {
            er.val /= ea.val + eb.val;
        };
    })
}

#[bench]
fn data_row(b: &mut test::Bencher) {
    let size = 1 << 20;
    let mut a = Vec::with_capacity(size);
    for i in 0..size {
        a.push(Data { id: i, val: 15., ..Data::default()});
    }
    b.bytes = (size_of::<usize>() * size) as u64;
    b.iter(|| {
        for mut e in a.iter_mut() {
            e.id *= 2;
        }
    })
}
<|endoftext|>


<commit_before>// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0

use crate::{
    indent::{IndentConfig, IndentedWriter},
    CodeGeneratorConfig,
};
use serde_reflection::{ContainerFormat, Format, Named, Registry, VariantFormat};
use std::collections::{BTreeMap, HashMap};
use std::io::{Result, Write};
use std::path::PathBuf;

/// Main configuration object for code-generation in Python.
pub struct CodeGenerator<'a> {
    /// Language-independent configuration.
    config: &'a CodeGeneratorConfig,
    /// Whether the module providing Serde definitions is located within package.
    serde_package_name: Option<String>,
    /// Mapping from external type names to suitably qualified names (e.g. "MyClass" -> "my_module.MyClass").
    /// Assumes suitable imports (e.g. "from my_package import my_module").
    /// Derived from `config.external_definitions`.
    external_qualified_names: HashMap<String, String>,
}

/// Shared state for the code generation of a Python source file.
struct PythonEmitter<'a, T> {
    /// Writer.
    out: IndentedWriter<T>,
    /// Generator.
    generator: &'a CodeGenerator<'a>,
    /// Current namespace (e.g. vec!["my_package", "my_module", "MyClass"])
    current_namespace: Vec<String>,
}

impl<'a> CodeGenerator<'a> {
    /// Create a Python code generator for the given config.
    pub fn new(config: &'a CodeGeneratorConfig) -> Self {
        let mut external_qualified_names = HashMap::new();
        for (module_path, names) in &config.external_definitions {
            let module = {
                let mut path = module_path.split('.').collect::<Vec<_>>();
                if path.len() < 2 {
                    module_path
                } else {
                    path.pop().unwrap()
                }
            };
            for name in names {
                external_qualified_names.insert(name.to_string(), format!("{}.{}", module, name));
            }
        }
        Self {
            config,
            serde_package_name: None,
            external_qualified_names,
        }
    }

    /// Whether the module providing Serde definitions is located within a package.
    pub fn with_serde_package_name(mut self, serde_package_name: Option<String>) -> Self {
        self.serde_package_name = serde_package_name;
        self
    }

    /// Write container definitions in Python.
    pub fn output(&self, out: &mut dyn Write, registry: &Registry) -> Result<()> {
        let current_namespace = self
            .config
            .module_name
            .split('.')
            .map(String::from)
            .collect();
        let mut emitter = PythonEmitter {
            out: IndentedWriter::new(out, IndentConfig::Space(4)),
            generator: self,
            current_namespace,
        };
        emitter.output_preamble()?;
        for (name, format) in registry {
            emitter.output_container(name, format)?;
        }
        Ok(())
    }
}

impl<'a, T> PythonEmitter<'a, T>
where
    T: Write,
{
    fn quote_import(&self, module: &str) -> String {
        let mut parts = module.split('.').collect::<Vec<_>>();
        if parts.len() <= 1 {
            format!("import {}", module)
        } else {
            let module_name = parts.pop().unwrap();
            format!("from {} import {}", parts.join("."), module_name)
        }
    }

    fn output_preamble(&mut self) -> Result<()> {
        writeln!(
            self.out,
            r#"# pyre-strict
from dataclasses import dataclass
import typing
{}import serde_types as st"#,
            match &self.generator.serde_package_name {
                None => "".to_string(),
                Some(name) => format!("from {} ", name),
            }
        )?;
        for module in self.generator.config.external_definitions.keys() {
            writeln!(self.out, "{}\n", self.quote_import(module),)?;
        }
        Ok(())
    }

    /// Compute a reference to the registry type `name`.
    /// Use a qualified name in case of external definitions.
    fn quote_qualified_name(&self, name: &str) -> String {
        self.generator
            .external_qualified_names
            .get(name)
            .cloned()
            .unwrap_or_else(|| {
                // Need quotes because of circular dependencies.
                format!("\"{}\"", name.to_string())
            })
    }

    fn quote_type(&self, format: &Format) -> String {
        use Format::*;
        match format {
            TypeName(x) => self.quote_qualified_name(x),
            Unit => "st.unit".into(),
            Bool => "st.bool".into(),
            I8 => "st.int8".into(),
            I16 => "st.int16".into(),
            I32 => "st.int32".into(),
            I64 => "st.int64".into(),
            I128 => "st.int128".into(),
            U8 => "st.uint8".into(),
            U16 => "st.uint16".into(),
            U32 => "st.uint32".into(),
            U64 => "st.uint64".into(),
            U128 => "st.uint128".into(),
            F32 => "st.float32".into(),
            F64 => "st.float64".into(),
            Char => "st.char".into(),
            Str => "str".into(),
            Bytes => "bytes".into(),

            Option(format) => format!("typing.Optional[{}]", self.quote_type(format)),
            Seq(format) => format!("typing.Sequence[{}]", self.quote_type(format)),
            Map { key, value } => format!(
                "typing.Dict[{}, {}]",
                self.quote_type(key),
                self.quote_type(value)
            ),
            Tuple(formats) => format!("typing.Tuple[{}]", self.quote_types(formats)),
            TupleArray { content, size } => format!(
                "typing.Tuple[{}]",
                self.quote_types(&vec![content.as_ref().clone(); *size])
            ), // Sadly, there are no fixed-size arrays in python.

            Variable(_) => panic!("unexpected value"),
        }
    }

    fn quote_types(&self, formats: &[Format]) -> String {
        formats
            .iter()
            .map(|x| self.quote_type(x))
            .collect::<Vec<_>>()
            .join(", ")
    }

    fn output_comment(&mut self, name: &str) -> std::io::Result<()> {
        let mut path = self.current_namespace.clone();
        path.push(name.to_string());
        if let Some(doc) = self.generator.config.comments.get(&path) {
            writeln!(self.out, "\"\"\"{}\n\"\"\"", doc)?;
        }
        Ok(())
    }

    fn output_fields(&mut self, fields: &[Named<Format>]) -> Result<()> {
        for field in fields {
            writeln!(
                self.out,
                "{}: {}",
                field.name,
                self.quote_type(&field.value)
            )?;
        }
        Ok(())
    }

    fn output_variant(
        &mut self,
        base: &str,
        name: &str,
        index: u32,
        variant: &VariantFormat,
    ) -> Result<()> {
        use VariantFormat::*;
        let fields = match variant {
            Unit => Vec::new(),
            NewType(format) => vec![Named {
                name: "value".to_string(),
                value: format.as_ref().clone(),
            }],
            Tuple(formats) => vec![Named {
                name: "value".to_string(),
                value: Format::Tuple(formats.clone()),
            }],
            Struct(fields) => fields.clone(),
            Variable(_) => panic!("incorrect value"),
        };

        // Regarding comments, we pretend the namespace is `[module, base, name]`.
        writeln!(self.out, "\n@dataclass\nclass {0}__{1}({0}):", base, name)?;
        self.out.indent();
        self.output_comment(&name)?;
        writeln!(self.out, "INDEX = {}  # type: int", index)?;
        self.current_namespace.push(name.to_string());
        self.output_fields(&fields)?;
        self.out.unindent();
        self.current_namespace.pop();
        writeln!(self.out)
    }

    fn output_enum_container(
        &mut self,
        name: &str,
        variants: &BTreeMap<u32, Named<VariantFormat>>,
    ) -> Result<()> {
        // Initializing VARIANTS with a temporary value for typechecking purposes.
        writeln!(self.out, "\nclass {}:", name)?;
        self.out.indent();
        self.output_comment(&name)?;
        writeln!(self.out, "VARIANTS = []  # type: typing.Sequence[typing.Type[{}]]\n", name)?;
        self.out.unindent();

        self.current_namespace.push(name.to_string());
        for (index, variant) in variants {
            self.output_variant(name, &variant.name, *index, &variant.value)?;
        }
        self.current_namespace.pop();

        writeln!(
            self.out,
            "{}.VARIANTS = [\n{}]\n",
            name,
            variants
                .iter()
                .map(|(_, v)| format!("    {}__{},\n", name, v.name))
                .collect::<Vec<_>>()
                .join("")
        )
    }

    fn output_container(&mut self, name: &str, format: &ContainerFormat) -> Result<()> {
        use ContainerFormat::*;
        let fields = match format {
            UnitStruct => Vec::new(),
            NewTypeStruct(format) => vec![Named {
                name: "value".to_string(),
                value: format.as_ref().clone(),
            }],
            TupleStruct(formats) => vec![Named {
                name: "value".to_string(),
                value: Format::Tuple(formats.clone()),
            }],
            Struct(fields) => fields.clone(),
            Enum(variants) => {
                // Enum case.
                self.output_enum_container(name, variants)?;
                return Ok(());
            }
        };
        // Struct case.
        writeln!(self.out, "\n@dataclass\nclass {}:", name)?;
        self.out.indent();
        self.output_comment(name)?;
        self.current_namespace.push(name.to_string());
        if fields.is_empty() {
            writeln!(self.out, "pass")?;
        } else {
            self.output_fields(&fields)?;
        }
        self.current_namespace.pop();
        self.out.unindent();
        writeln!(self.out)
    }
}

/// Installer for generated source files in Python.
pub struct Installer {
    install_dir: PathBuf,
    serde_package_name: Option<String>,
}

impl Installer {
    pub fn new(install_dir: PathBuf, serde_package_name: Option<String>) -> Self {
        Installer {
            install_dir,
            serde_package_name,
        }
    }

    fn create_module_init_file(&self, name: &str) -> Result<std::fs::File> {
        let dir_path = self.install_dir.join(name);
        std::fs::create_dir_all(&dir_path)?;
        std::fs::File::create(dir_path.join("__init__.py"))
    }

    fn fix_serde_package(&self, content: &str) -> String {
        match &self.serde_package_name {
            None => content.into(),
            Some(name) => content.replace(
                "import serde_types",
                &format!("from {} import serde_types", name),
            ),
        }
    }
}

impl crate::SourceInstaller for Installer {
    type Error = Box<dyn std::error::Error>;

    fn install_module(
        &self,
        config: &crate::CodeGeneratorConfig,
        registry: &Registry,
    ) -> std::result::Result<(), Self::Error> {
        let mut file = self.create_module_init_file(&config.module_name)?;
        let generator =
            CodeGenerator::new(config).with_serde_package_name(self.serde_package_name.clone());
        generator.output(&mut file, registry)?;
        Ok(())
    }

    fn install_serde_runtime(&self) -> std::result::Result<(), Self::Error> {
        let mut file = self.create_module_init_file("serde_types")?;
        write!(
            file,
            "{}",
            self.fix_serde_package(include_str!("../runtime/python/serde_types/__init__.py"))
        )?;
        Ok(())
    }

    fn install_bincode_runtime(&self) -> std::result::Result<(), Self::Error> {
        let mut file = self.create_module_init_file("bincode")?;
        write!(
            file,
            "{}",
            self.fix_serde_package(include_str!("../runtime/python/bincode/__init__.py"))
        )?;
        Ok(())
    }

    fn install_lcs_runtime(&self) -> std::result::Result<(), Self::Error> {
        let mut file = self.create_module_init_file("lcs")?;
        write!(
            file,
            "{}",
            self.fix_serde_package(include_str!("../runtime/python/lcs/__init__.py"))
        )?;
        Ok(())
    }
}
<commit_msg>[serde generate] python: omit INDEX and VARIANTS when serialization is skipped<commit_after>// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0

use crate::{
    indent::{IndentConfig, IndentedWriter},
    CodeGeneratorConfig,
};
use serde_reflection::{ContainerFormat, Format, Named, Registry, VariantFormat};
use std::collections::{BTreeMap, HashMap};
use std::io::{Result, Write};
use std::path::PathBuf;

/// Main configuration object for code-generation in Python.
pub struct CodeGenerator<'a> {
    /// Language-independent configuration.
    config: &'a CodeGeneratorConfig,
    /// Whether the module providing Serde definitions is located within package.
    serde_package_name: Option<String>,
    /// Mapping from external type names to suitably qualified names (e.g. "MyClass" -> "my_module.MyClass").
    /// Assumes suitable imports (e.g. "from my_package import my_module").
    /// Derived from `config.external_definitions`.
    external_qualified_names: HashMap<String, String>,
}

/// Shared state for the code generation of a Python source file.
struct PythonEmitter<'a, T> {
    /// Writer.
    out: IndentedWriter<T>,
    /// Generator.
    generator: &'a CodeGenerator<'a>,
    /// Current namespace (e.g. vec!["my_package", "my_module", "MyClass"])
    current_namespace: Vec<String>,
}

impl<'a> CodeGenerator<'a> {
    /// Create a Python code generator for the given config.
    pub fn new(config: &'a CodeGeneratorConfig) -> Self {
        let mut external_qualified_names = HashMap::new();
        for (module_path, names) in &config.external_definitions {
            let module = {
                let mut path = module_path.split('.').collect::<Vec<_>>();
                if path.len() < 2 {
                    module_path
                } else {
                    path.pop().unwrap()
                }
            };
            for name in names {
                external_qualified_names.insert(name.to_string(), format!("{}.{}", module, name));
            }
        }
        Self {
            config,
            serde_package_name: None,
            external_qualified_names,
        }
    }

    /// Whether the module providing Serde definitions is located within a package.
    pub fn with_serde_package_name(mut self, serde_package_name: Option<String>) -> Self {
        self.serde_package_name = serde_package_name;
        self
    }

    /// Write container definitions in Python.
    pub fn output(&self, out: &mut dyn Write, registry: &Registry) -> Result<()> {
        let current_namespace = self
            .config
            .module_name
            .split('.')
            .map(String::from)
            .collect();
        let mut emitter = PythonEmitter {
            out: IndentedWriter::new(out, IndentConfig::Space(4)),
            generator: self,
            current_namespace,
        };
        emitter.output_preamble()?;
        for (name, format) in registry {
            emitter.output_container(name, format)?;
        }
        Ok(())
    }
}

impl<'a, T> PythonEmitter<'a, T>
where
    T: Write,
{
    fn quote_import(&self, module: &str) -> String {
        let mut parts = module.split('.').collect::<Vec<_>>();
        if parts.len() <= 1 {
            format!("import {}", module)
        } else {
            let module_name = parts.pop().unwrap();
            format!("from {} import {}", parts.join("."), module_name)
        }
    }

    fn output_preamble(&mut self) -> Result<()> {
        writeln!(
            self.out,
            r#"# pyre-strict
from dataclasses import dataclass
import typing
{}import serde_types as st"#,
            match &self.generator.serde_package_name {
                None => "".to_string(),
                Some(name) => format!("from {} ", name),
            }
        )?;
        for module in self.generator.config.external_definitions.keys() {
            writeln!(self.out, "{}\n", self.quote_import(module),)?;
        }
        Ok(())
    }

    /// Compute a reference to the registry type `name`.
    /// Use a qualified name in case of external definitions.
    fn quote_qualified_name(&self, name: &str) -> String {
        self.generator
            .external_qualified_names
            .get(name)
            .cloned()
            .unwrap_or_else(|| {
                // Need quotes because of circular dependencies.
                format!("\"{}\"", name.to_string())
            })
    }

    fn quote_type(&self, format: &Format) -> String {
        use Format::*;
        match format {
            TypeName(x) => self.quote_qualified_name(x),
            Unit => "st.unit".into(),
            Bool => "st.bool".into(),
            I8 => "st.int8".into(),
            I16 => "st.int16".into(),
            I32 => "st.int32".into(),
            I64 => "st.int64".into(),
            I128 => "st.int128".into(),
            U8 => "st.uint8".into(),
            U16 => "st.uint16".into(),
            U32 => "st.uint32".into(),
            U64 => "st.uint64".into(),
            U128 => "st.uint128".into(),
            F32 => "st.float32".into(),
            F64 => "st.float64".into(),
            Char => "st.char".into(),
            Str => "str".into(),
            Bytes => "bytes".into(),

            Option(format) => format!("typing.Optional[{}]", self.quote_type(format)),
            Seq(format) => format!("typing.Sequence[{}]", self.quote_type(format)),
            Map { key, value } => format!(
                "typing.Dict[{}, {}]",
                self.quote_type(key),
                self.quote_type(value)
            ),
            Tuple(formats) => format!("typing.Tuple[{}]", self.quote_types(formats)),
            TupleArray { content, size } => format!(
                "typing.Tuple[{}]",
                self.quote_types(&vec![content.as_ref().clone(); *size])
            ), // Sadly, there are no fixed-size arrays in python.

            Variable(_) => panic!("unexpected value"),
        }
    }

    fn quote_types(&self, formats: &[Format]) -> String {
        formats
            .iter()
            .map(|x| self.quote_type(x))
            .collect::<Vec<_>>()
            .join(", ")
    }

    fn output_comment(&mut self, name: &str) -> std::io::Result<()> {
        let mut path = self.current_namespace.clone();
        path.push(name.to_string());
        if let Some(doc) = self.generator.config.comments.get(&path) {
            writeln!(self.out, "\"\"\"{}\n\"\"\"", doc)?;
        }
        Ok(())
    }

    fn output_fields(&mut self, fields: &[Named<Format>]) -> Result<()> {
        if fields.is_empty() {
            writeln!(self.out, "pass")?;
            return Ok(());
        }
        for field in fields {
            writeln!(
                self.out,
                "{}: {}",
                field.name,
                self.quote_type(&field.value)
            )?;
        }
        Ok(())
    }

    fn output_variant(
        &mut self,
        base: &str,
        name: &str,
        index: u32,
        variant: &VariantFormat,
    ) -> Result<()> {
        use VariantFormat::*;
        let fields = match variant {
            Unit => Vec::new(),
            NewType(format) => vec![Named {
                name: "value".to_string(),
                value: format.as_ref().clone(),
            }],
            Tuple(formats) => vec![Named {
                name: "value".to_string(),
                value: Format::Tuple(formats.clone()),
            }],
            Struct(fields) => fields.clone(),
            Variable(_) => panic!("incorrect value"),
        };

        // Regarding comments, we pretend the namespace is `[module, base, name]`.
        writeln!(self.out, "\n@dataclass\nclass {0}__{1}({0}):", base, name)?;
        self.out.indent();
        self.output_comment(&name)?;
        if self.generator.config.serialization {
            writeln!(self.out, "INDEX = {}  # type: int", index)?;
        }
        self.current_namespace.push(name.to_string());
        self.output_fields(&fields)?;
        self.out.unindent();
        self.current_namespace.pop();
        writeln!(self.out)
    }

    fn output_enum_container(
        &mut self,
        name: &str,
        variants: &BTreeMap<u32, Named<VariantFormat>>,
    ) -> Result<()> {
        writeln!(self.out, "\nclass {}:", name)?;
        self.out.indent();
        self.output_comment(&name)?;
        if self.generator.config.serialization {
            writeln!(
                self.out,
                "VARIANTS = []  # type: typing.Sequence[typing.Type[{}]]\n",
                name
            )?;
        } else {
            writeln!(self.out, "pass\n")?;
        }
        self.out.unindent();

        self.current_namespace.push(name.to_string());
        for (index, variant) in variants {
            self.output_variant(name, &variant.name, *index, &variant.value)?;
        }
        self.current_namespace.pop();

        if self.generator.config.serialization {
            writeln!(
                self.out,
                "{}.VARIANTS = [\n{}]\n",
                name,
                variants
                    .iter()
                    .map(|(_, v)| format!("    {}__{},\n", name, v.name))
                    .collect::<Vec<_>>()
                    .join("")
            )?;
        }
        Ok(())
    }

    fn output_container(&mut self, name: &str, format: &ContainerFormat) -> Result<()> {
        use ContainerFormat::*;
        let fields = match format {
            UnitStruct => Vec::new(),
            NewTypeStruct(format) => vec![Named {
                name: "value".to_string(),
                value: format.as_ref().clone(),
            }],
            TupleStruct(formats) => vec![Named {
                name: "value".to_string(),
                value: Format::Tuple(formats.clone()),
            }],
            Struct(fields) => fields.clone(),
            Enum(variants) => {
                // Enum case.
                self.output_enum_container(name, variants)?;
                return Ok(());
            }
        };
        // Struct case.
        writeln!(self.out, "\n@dataclass\nclass {}:", name)?;
        self.out.indent();
        self.output_comment(name)?;
        self.current_namespace.push(name.to_string());
        self.output_fields(&fields)?;
        self.current_namespace.pop();
        self.out.unindent();
        writeln!(self.out)
    }
}

/// Installer for generated source files in Python.
pub struct Installer {
    install_dir: PathBuf,
    serde_package_name: Option<String>,
}

impl Installer {
    pub fn new(install_dir: PathBuf, serde_package_name: Option<String>) -> Self {
        Installer {
            install_dir,
            serde_package_name,
        }
    }

    fn create_module_init_file(&self, name: &str) -> Result<std::fs::File> {
        let dir_path = self.install_dir.join(name);
        std::fs::create_dir_all(&dir_path)?;
        std::fs::File::create(dir_path.join("__init__.py"))
    }

    fn fix_serde_package(&self, content: &str) -> String {
        match &self.serde_package_name {
            None => content.into(),
            Some(name) => content.replace(
                "import serde_types",
                &format!("from {} import serde_types", name),
            ),
        }
    }
}

impl crate::SourceInstaller for Installer {
    type Error = Box<dyn std::error::Error>;

    fn install_module(
        &self,
        config: &crate::CodeGeneratorConfig,
        registry: &Registry,
    ) -> std::result::Result<(), Self::Error> {
        let mut file = self.create_module_init_file(&config.module_name)?;
        let generator =
            CodeGenerator::new(config).with_serde_package_name(self.serde_package_name.clone());
        generator.output(&mut file, registry)?;
        Ok(())
    }

    fn install_serde_runtime(&self) -> std::result::Result<(), Self::Error> {
        let mut file = self.create_module_init_file("serde_types")?;
        write!(
            file,
            "{}",
            self.fix_serde_package(include_str!("../runtime/python/serde_types/__init__.py"))
        )?;
        Ok(())
    }

    fn install_bincode_runtime(&self) -> std::result::Result<(), Self::Error> {
        let mut file = self.create_module_init_file("bincode")?;
        write!(
            file,
            "{}",
            self.fix_serde_package(include_str!("../runtime/python/bincode/__init__.py"))
        )?;
        Ok(())
    }

    fn install_lcs_runtime(&self) -> std::result::Result<(), Self::Error> {
        let mut file = self.create_module_init_file("lcs")?;
        write!(
            file,
            "{}",
            self.fix_serde_package(include_str!("../runtime/python/lcs/__init__.py"))
        )?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.24.1")]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        cyclomatic_complexity,
        doc_markdown,
        match_same_arms,
        redundant_field_names
    )
)]

#[macro_use]
extern crate syn;

extern crate proc_macro2;
extern crate quote;

#[path = "src/mod.rs"]
mod internals;

pub use internals::*;
<commit_msg>Update serde_derive_internals ignored lints<commit_after>#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.24.1")]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        cyclomatic_complexity,
        redundant_field_names,
        trivially_copy_pass_by_ref
    )
)]

#[macro_use]
extern crate syn;

extern crate proc_macro2;
extern crate quote;

#[path = "src/mod.rs"]
mod internals;

pub use internals::*;
<|endoftext|>


<commit_before>#![feature(custom_attribute, custom_derive, plugin)]
#![plugin(serde_macros)]

extern crate serde;

#[derive(Serialize)]
#[serde(abc="xyz")] //~ unknown serde container attribute `abc = "xyz"`
struct Foo {
    x: u32,
}

#[derive(Deserialize)]
#[serde(abc="xyz")] //~ unknown serde container attribute `abc = "xyz"`
struct Foo {
    x: u32,
}

#[derive(Serialize)]
struct Foo {
    #[serde(abc="xyz")] //~ unknown serde field attribute `abc = "xyz"`
    x: u32,
}

#[derive(Deserialize)]
struct Foo {
    #[serde(abc="xyz")] //~ unknown serde field attribute `abc = "xyz"`
    x: u32,
}

fn main() { }
<commit_msg>Fix compiletest error in newest nightly<commit_after>#![feature(custom_attribute, custom_derive, plugin)]
#![plugin(serde_macros)]

extern crate serde;

#[derive(Serialize)]
#[serde(abc="xyz")] //~ unknown serde container attribute `abc = "xyz"`
struct A {
    x: u32,
}

#[derive(Deserialize)]
#[serde(abc="xyz")] //~ unknown serde container attribute `abc = "xyz"`
struct B {
    x: u32,
}

#[derive(Serialize)]
struct C {
    #[serde(abc="xyz")] //~ unknown serde field attribute `abc = "xyz"`
    x: u32,
}

#[derive(Deserialize)]
struct D {
    #[serde(abc="xyz")] //~ unknown serde field attribute `abc = "xyz"`
    x: u32,
}

fn main() { }
<|endoftext|>


<commit_before>use clock::Clock;

//
// Clock Creation
//

#[test]
fn test_on_the_hour() {
    assert_eq!(Clock::new(8, 0).to_string(), "08:00");
}

#[test]
#[ignore]
fn test_past_the_hour() {
    assert_eq!(Clock::new(11, 9).to_string(), "11:09");
}

#[test]
#[ignore]
fn test_midnight_is_zero_hours() {
    assert_eq!(Clock::new(24, 0).to_string(), "00:00");
}

#[test]
#[ignore]
fn test_hour_rolls_over() {
    assert_eq!(Clock::new(25, 0).to_string(), "01:00");
}

#[test]
#[ignore]
fn test_hour_rolls_over_continuously() {
    assert_eq!(Clock::new(100, 0).to_string(), "04:00");
}

#[test]
#[ignore]
fn test_sixty_minutes_is_next_hour() {
    assert_eq!(Clock::new(1, 60).to_string(), "02:00");
}

#[test]
#[ignore]
fn test_minutes_roll_over() {
    assert_eq!(Clock::new(0, 160).to_string(), "02:40");
}

#[test]
#[ignore]
fn test_minutes_roll_over_continuously() {
    assert_eq!(Clock::new(0, 1723).to_string(), "04:43");
}

#[test]
#[ignore]
fn test_hours_and_minutes_roll_over() {
    assert_eq!(Clock::new(25, 160).to_string(), "03:40");
}

#[test]
#[ignore]
fn test_hours_and_minutes_roll_over_continuously() {
    assert_eq!(Clock::new(201, 3001).to_string(), "11:01");
}

#[test]
#[ignore]
fn test_hours_and_minutes_roll_over_to_exactly_midnight() {
    assert_eq!(Clock::new(72, 8640).to_string(), "00:00");
}

#[test]
#[ignore]
fn test_negative_hour() {
    assert_eq!(Clock::new(-1, 15).to_string(), "23:15");
}

#[test]
#[ignore]
fn test_negative_hour_roll_over() {
    assert_eq!(Clock::new(-25, 00).to_string(), "23:00");
}

#[test]
#[ignore]
fn test_negative_hour_roll_over_continuously() {
    assert_eq!(Clock::new(-91, 00).to_string(), "05:00");
}

#[test]
#[ignore]
fn test_negative_minutes() {
    assert_eq!(Clock::new(1, -40).to_string(), "00:20");
}

#[test]
#[ignore]
fn test_negative_minutes_roll_over() {
    assert_eq!(Clock::new(1, -160).to_string(), "22:20");
}

#[test]
#[ignore]
fn test_negative_minutes_roll_over_continuously() {
    assert_eq!(Clock::new(1, -4820).to_string(), "16:40");
}

#[test]
#[ignore]
fn test_negative_sixty_minutes_is_prev_hour() {
    assert_eq!(Clock::new(2, -60).to_string(), "01:00");
}

#[test]
#[ignore]
fn test_negative_one_twenty_minutes_is_two_prev_hours() {
    assert_eq!(Clock::new(1, -120).to_string(), "23:00");
}

#[test]
#[ignore]
fn test_negative_hour_and_minutes_both_roll_over() {
    assert_eq!(Clock::new(-25, -160).to_string(), "20:20");
}

#[test]
#[ignore]
fn test_negative_hour_and_minutes_both_roll_over_continuously() {
    assert_eq!(Clock::new(-121, -5810).to_string(), "22:10");
}

#[test]
#[ignore]
fn test_zero_hour_and_negative_minutes() {
    assert_eq!(Clock::new(0, -22).to_string(), "23:38");
}

//
// Clock Math
//

#[test]
#[ignore]
fn test_add_minutes() {
    let clock = Clock::new(10, 0).add_minutes(3);
    assert_eq!(clock.to_string(), "10:03");
}

#[test]
#[ignore]
fn test_add_no_minutes() {
    let clock = Clock::new(6, 41).add_minutes(0);
    assert_eq!(clock.to_string(), "06:41");
}

#[test]
#[ignore]
fn test_add_to_next_hour() {
    let clock = Clock::new(0, 45).add_minutes(40);
    assert_eq!(clock.to_string(), "01:25");
}

#[test]
#[ignore]
fn test_add_more_than_one_hour() {
    let clock = Clock::new(10, 0).add_minutes(61);
    assert_eq!(clock.to_string(), "11:01");
}

#[test]
#[ignore]
fn test_add_more_than_two_hours_with_carry() {
    let clock = Clock::new(0, 45).add_minutes(160);
    assert_eq!(clock.to_string(), "03:25");
}

#[test]
#[ignore]
fn test_add_across_midnight() {
    let clock = Clock::new(23, 59).add_minutes(2);
    assert_eq!(clock.to_string(), "00:01");
}

#[test]
#[ignore]
fn test_add_more_than_one_day() {
    let clock = Clock::new(5, 32).add_minutes(1500);
    assert_eq!(clock.to_string(), "06:32");
}

#[test]
#[ignore]
fn test_add_more_than_two_days() {
    let clock = Clock::new(1, 1).add_minutes(3500);
    assert_eq!(clock.to_string(), "11:21");
}

#[test]
#[ignore]
fn test_subtract_minutes() {
    let clock = Clock::new(10, 3).add_minutes(-3);
    assert_eq!(clock.to_string(), "10:00");
}

#[test]
#[ignore]
fn test_subtract_to_previous_hour() {
    let clock = Clock::new(10, 3).add_minutes(-30);
    assert_eq!(clock.to_string(), "09:33");
}

#[test]
#[ignore]
fn test_subtract_more_than_an_hour() {
    let clock = Clock::new(10, 3).add_minutes(-70);
    assert_eq!(clock.to_string(), "08:53");
}

#[test]
#[ignore]
fn test_subtract_across_midnight() {
    let clock = Clock::new(0, 3).add_minutes(-4);
    assert_eq!(clock.to_string(), "23:59");
}

#[test]
#[ignore]
fn test_subtract_more_than_two_hours() {
    let clock = Clock::new(0, 0).add_minutes(-160);
    assert_eq!(clock.to_string(), "21:20");
}

#[test]
#[ignore]
fn test_subtract_more_than_two_hours_with_borrow() {
    let clock = Clock::new(6, 15).add_minutes(-160);
    assert_eq!(clock.to_string(), "03:35");
}

#[test]
#[ignore]
fn test_subtract_more_than_one_day() {
    let clock = Clock::new(5, 32).add_minutes(-1500);
    assert_eq!(clock.to_string(), "04:32");
}

#[test]
#[ignore]
fn test_subtract_more_than_two_days() {
    let clock = Clock::new(2, 20).add_minutes(-3000);
    assert_eq!(clock.to_string(), "00:20");
}

//
// Test Equality
//

#[test]
#[ignore]
fn test_compare_clocks_for_equality() {
    assert_eq!(Clock::new(15, 37), Clock::new(15, 37));
}

#[test]
#[ignore]
fn test_compare_clocks_a_minute_apart() {
    assert_ne!(Clock::new(15, 36), Clock::new(15, 37));
}

#[test]
#[ignore]
fn test_compare_clocks_an_hour_apart() {
    assert_ne!(Clock::new(14, 37), Clock::new(15, 37));
}

#[test]
#[ignore]
fn test_compare_clocks_with_hour_overflow() {
    assert_eq!(Clock::new(10, 37), Clock::new(34, 37));
}

#[test]
#[ignore]
fn test_compare_clocks_with_hour_overflow_by_several_days() {
    assert_eq!(Clock::new(3, 11), Clock::new(99, 11));
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hour() {
    assert_eq!(Clock::new(22, 40), Clock::new(-2, 40));
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hour_that_wraps() {
    assert_eq!(Clock::new(17, 3), Clock::new(-31, 3));
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hour_that_wraps_multiple_times() {
    assert_eq!(Clock::new(13, 49), Clock::new(-83, 49));
}

#[test]
#[ignore]
fn test_compare_clocks_with_minutes_overflow() {
    assert_eq!(Clock::new(0, 1), Clock::new(0, 1441));
}

#[test]
#[ignore]
fn test_compare_clocks_with_minutes_overflow_by_several_days() {
    assert_eq!(Clock::new(2, 2), Clock::new(2, 4322));
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_minute() {
    assert_eq!(Clock::new(2, 40), Clock::new(3, -20))
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_minute_that_wraps() {
    assert_eq!(Clock::new(4, 10), Clock::new(5, -1490))
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_minute_that_wraps_multiple() {
    assert_eq!(Clock::new(6, 15), Clock::new(6, -4305))
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hours_and_minutes() {
    assert_eq!(Clock::new(7, 32), Clock::new(-12, -268))
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hours_and_minutes_that_wrap() {
    assert_eq!(Clock::new(18, 7), Clock::new(-54, -11_513))
}

#[test]
#[ignore]
fn test_compare_full_clock_and_zeroed_clock() {
    assert_eq!(Clock::new(24, 0), Clock::new(0, 0))
}
<commit_msg>Make all expected values on the right (#1326)<commit_after>use clock::Clock;

//
// Clock Creation
//

#[test]
fn test_on_the_hour() {
    assert_eq!(Clock::new(8, 0).to_string(), "08:00");
}

#[test]
#[ignore]
fn test_past_the_hour() {
    assert_eq!(Clock::new(11, 9).to_string(), "11:09");
}

#[test]
#[ignore]
fn test_midnight_is_zero_hours() {
    assert_eq!(Clock::new(24, 0).to_string(), "00:00");
}

#[test]
#[ignore]
fn test_hour_rolls_over() {
    assert_eq!(Clock::new(25, 0).to_string(), "01:00");
}

#[test]
#[ignore]
fn test_hour_rolls_over_continuously() {
    assert_eq!(Clock::new(100, 0).to_string(), "04:00");
}

#[test]
#[ignore]
fn test_sixty_minutes_is_next_hour() {
    assert_eq!(Clock::new(1, 60).to_string(), "02:00");
}

#[test]
#[ignore]
fn test_minutes_roll_over() {
    assert_eq!(Clock::new(0, 160).to_string(), "02:40");
}

#[test]
#[ignore]
fn test_minutes_roll_over_continuously() {
    assert_eq!(Clock::new(0, 1723).to_string(), "04:43");
}

#[test]
#[ignore]
fn test_hours_and_minutes_roll_over() {
    assert_eq!(Clock::new(25, 160).to_string(), "03:40");
}

#[test]
#[ignore]
fn test_hours_and_minutes_roll_over_continuously() {
    assert_eq!(Clock::new(201, 3001).to_string(), "11:01");
}

#[test]
#[ignore]
fn test_hours_and_minutes_roll_over_to_exactly_midnight() {
    assert_eq!(Clock::new(72, 8640).to_string(), "00:00");
}

#[test]
#[ignore]
fn test_negative_hour() {
    assert_eq!(Clock::new(-1, 15).to_string(), "23:15");
}

#[test]
#[ignore]
fn test_negative_hour_roll_over() {
    assert_eq!(Clock::new(-25, 00).to_string(), "23:00");
}

#[test]
#[ignore]
fn test_negative_hour_roll_over_continuously() {
    assert_eq!(Clock::new(-91, 00).to_string(), "05:00");
}

#[test]
#[ignore]
fn test_negative_minutes() {
    assert_eq!(Clock::new(1, -40).to_string(), "00:20");
}

#[test]
#[ignore]
fn test_negative_minutes_roll_over() {
    assert_eq!(Clock::new(1, -160).to_string(), "22:20");
}

#[test]
#[ignore]
fn test_negative_minutes_roll_over_continuously() {
    assert_eq!(Clock::new(1, -4820).to_string(), "16:40");
}

#[test]
#[ignore]
fn test_negative_sixty_minutes_is_prev_hour() {
    assert_eq!(Clock::new(2, -60).to_string(), "01:00");
}

#[test]
#[ignore]
fn test_negative_one_twenty_minutes_is_two_prev_hours() {
    assert_eq!(Clock::new(1, -120).to_string(), "23:00");
}

#[test]
#[ignore]
fn test_negative_hour_and_minutes_both_roll_over() {
    assert_eq!(Clock::new(-25, -160).to_string(), "20:20");
}

#[test]
#[ignore]
fn test_negative_hour_and_minutes_both_roll_over_continuously() {
    assert_eq!(Clock::new(-121, -5810).to_string(), "22:10");
}

#[test]
#[ignore]
fn test_zero_hour_and_negative_minutes() {
    assert_eq!(Clock::new(0, -22).to_string(), "23:38");
}

//
// Clock Math
//

#[test]
#[ignore]
fn test_add_minutes() {
    let clock = Clock::new(10, 0).add_minutes(3);
    assert_eq!(clock.to_string(), "10:03");
}

#[test]
#[ignore]
fn test_add_no_minutes() {
    let clock = Clock::new(6, 41).add_minutes(0);
    assert_eq!(clock.to_string(), "06:41");
}

#[test]
#[ignore]
fn test_add_to_next_hour() {
    let clock = Clock::new(0, 45).add_minutes(40);
    assert_eq!(clock.to_string(), "01:25");
}

#[test]
#[ignore]
fn test_add_more_than_one_hour() {
    let clock = Clock::new(10, 0).add_minutes(61);
    assert_eq!(clock.to_string(), "11:01");
}

#[test]
#[ignore]
fn test_add_more_than_two_hours_with_carry() {
    let clock = Clock::new(0, 45).add_minutes(160);
    assert_eq!(clock.to_string(), "03:25");
}

#[test]
#[ignore]
fn test_add_across_midnight() {
    let clock = Clock::new(23, 59).add_minutes(2);
    assert_eq!(clock.to_string(), "00:01");
}

#[test]
#[ignore]
fn test_add_more_than_one_day() {
    let clock = Clock::new(5, 32).add_minutes(1500);
    assert_eq!(clock.to_string(), "06:32");
}

#[test]
#[ignore]
fn test_add_more_than_two_days() {
    let clock = Clock::new(1, 1).add_minutes(3500);
    assert_eq!(clock.to_string(), "11:21");
}

#[test]
#[ignore]
fn test_subtract_minutes() {
    let clock = Clock::new(10, 3).add_minutes(-3);
    assert_eq!(clock.to_string(), "10:00");
}

#[test]
#[ignore]
fn test_subtract_to_previous_hour() {
    let clock = Clock::new(10, 3).add_minutes(-30);
    assert_eq!(clock.to_string(), "09:33");
}

#[test]
#[ignore]
fn test_subtract_more_than_an_hour() {
    let clock = Clock::new(10, 3).add_minutes(-70);
    assert_eq!(clock.to_string(), "08:53");
}

#[test]
#[ignore]
fn test_subtract_across_midnight() {
    let clock = Clock::new(0, 3).add_minutes(-4);
    assert_eq!(clock.to_string(), "23:59");
}

#[test]
#[ignore]
fn test_subtract_more_than_two_hours() {
    let clock = Clock::new(0, 0).add_minutes(-160);
    assert_eq!(clock.to_string(), "21:20");
}

#[test]
#[ignore]
fn test_subtract_more_than_two_hours_with_borrow() {
    let clock = Clock::new(6, 15).add_minutes(-160);
    assert_eq!(clock.to_string(), "03:35");
}

#[test]
#[ignore]
fn test_subtract_more_than_one_day() {
    let clock = Clock::new(5, 32).add_minutes(-1500);
    assert_eq!(clock.to_string(), "04:32");
}

#[test]
#[ignore]
fn test_subtract_more_than_two_days() {
    let clock = Clock::new(2, 20).add_minutes(-3000);
    assert_eq!(clock.to_string(), "00:20");
}

//
// Test Equality
//

#[test]
#[ignore]
fn test_compare_clocks_for_equality() {
    assert_eq!(Clock::new(15, 37), Clock::new(15, 37));
}

#[test]
#[ignore]
fn test_compare_clocks_a_minute_apart() {
    assert_ne!(Clock::new(15, 36), Clock::new(15, 37));
}

#[test]
#[ignore]
fn test_compare_clocks_an_hour_apart() {
    assert_ne!(Clock::new(14, 37), Clock::new(15, 37));
}

#[test]
#[ignore]
fn test_compare_clocks_with_hour_overflow() {
    assert_eq!(Clock::new(10, 37), Clock::new(34, 37));
}

#[test]
#[ignore]
fn test_compare_clocks_with_hour_overflow_by_several_days() {
    assert_eq!(Clock::new(99, 11), Clock::new(3, 11));
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hour() {
    assert_eq!(Clock::new(-2, 40), Clock::new(22, 40));
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hour_that_wraps() {
    assert_eq!(Clock::new(-31, 3), Clock::new(17, 3));
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hour_that_wraps_multiple_times() {
    assert_eq!(Clock::new(-83, 49), Clock::new(13, 49));
}

#[test]
#[ignore]
fn test_compare_clocks_with_minutes_overflow() {
    assert_eq!(Clock::new(0, 1441), Clock::new(0, 1));
}

#[test]
#[ignore]
fn test_compare_clocks_with_minutes_overflow_by_several_days() {
    assert_eq!(Clock::new(2, 4322), Clock::new(2, 2));
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_minute() {
    assert_eq!(Clock::new(3, -20), Clock::new(2, 40))
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_minute_that_wraps() {
    assert_eq!(Clock::new(5, -1490), Clock::new(4, 10))
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_minute_that_wraps_multiple() {
    assert_eq!(Clock::new(6, -4305), Clock::new(6, 15))
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hours_and_minutes() {
    assert_eq!(Clock::new(-12, -268), Clock::new(7, 32))
}

#[test]
#[ignore]
fn test_compare_clocks_with_negative_hours_and_minutes_that_wrap() {
    assert_eq!(Clock::new(-54, -11_513), Clock::new(18, 7))
}

#[test]
#[ignore]
fn test_compare_full_clock_and_zeroed_clock() {
    assert_eq!(Clock::new(24, 0), Clock::new(0, 0))
}
<|endoftext|>


<commit_before>use proc_macro::{Ident, TokenStream, TokenTree};

pub(crate) fn build(
    mod_name: Ident,
    ty: TokenTree,
    format: TokenStream,
    raw_format_string: Option<String>,
) -> TokenStream {
    let ty_s = &*ty.to_string();

    let format_description_display = raw_format_string.unwrap_or_else(|| format.to_string());

    let visitor = quote! {
        struct Visitor;
        struct OptionVisitor;

        impl<'a> ::serde::de::Visitor<'a> for Visitor {
            type Value = __TimeSerdeType;

            fn expecting(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
                write!(
                    f,
                    concat!(
                        "a(n) `",
                        #(ty_s),
                        "` in the format \"{}\"",
                    ),
                    #(format_description_display.as_str())
                )
            }

            fn visit_str<E: ::serde::de::Error>(
                self,
                value: &str
            ) -> Result<__TimeSerdeType, E> {
                __TimeSerdeType::parse(value, &DESCRIPTION).map_err(E::custom)
            }
        }

        impl<'a> ::serde::de::Visitor<'a> for OptionVisitor {
            type Value = Option<__TimeSerdeType>;

            fn expecting(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
                write!(
                    f,
                    concat!(
                        "an `Option<",
                        #(ty_s),
                        ">` in the format \"{}\"",
                    ),
                    #(format_description_display.as_str())
                )
            }

            fn visit_some<D: ::serde::de::Deserializer<'a>>(
                self,
                deserializer: D
            ) -> Result<Option<__TimeSerdeType>, D::Error> {
                deserializer
                    .deserialize_any(Visitor)
                    .map(Some)
            }

            fn visit_none<E: ::serde::de::Error>(
                self
            ) -> Result<Option<__TimeSerdeType>, E> {
                Ok(None)
            }
        }

    };

    let primary_fns = quote! {
        pub fn serialize<S: ::serde::Serializer>(
            datetime: &__TimeSerdeType,
            serializer: S,
        ) -> Result<S::Ok, S::Error> {
            use ::serde::Serialize;
            datetime
                .format(&DESCRIPTION)
                .map_err(::time::error::Format::into_invalid_serde_value::<S>)?
                .serialize(serializer)
        }

        pub fn deserialize<'a, D: ::serde::Deserializer<'a>>(
            deserializer: D
        ) -> Result<__TimeSerdeType, D::Error> {
            use ::serde::Deserialize;
            deserializer.deserialize_any(Visitor)
        }
    };

    let options_fns = quote! {
        pub fn serialize<S: ::serde::Serializer>(
            option: &Option<__TimeSerdeType>,
            serializer: S,
        ) -> Result<S::Ok, S::Error> {
            use ::serde::Serialize;
            option.map(|datetime| datetime.format(&DESCRIPTION))
                .transpose()
                .map_err(::time::error::Format::into_invalid_serde_value::<S>)?
                .serialize(serializer)
        }

        pub fn deserialize<'a, D: ::serde::Deserializer<'a>>(
            deserializer: D
        ) -> Result<Option<__TimeSerdeType>, D::Error> {
            use ::serde::Deserialize;
            deserializer.deserialize_option(OptionVisitor)
        }
    };

    quote! {
        mod #(mod_name) {
            use ::time::#(ty) as __TimeSerdeType;

            const DESCRIPTION: &[::time::format_description::FormatItem<'_>] = #S(format);

            #S(visitor)
            #S(primary_fns)

            pub(super) mod option {
                use super::{DESCRIPTION, OptionVisitor, Visitor, __TimeSerdeType};

                #S(options_fns)
            }
        }
    }
}
<commit_msg>Fix gating for `time::serde::format_description!`<commit_after>use proc_macro::{Ident, TokenStream, TokenTree};

pub(crate) fn build(
    mod_name: Ident,
    ty: TokenTree,
    format: TokenStream,
    raw_format_string: Option<String>,
) -> TokenStream {
    let ty_s = &*ty.to_string();

    let format_description_display = raw_format_string.unwrap_or_else(|| format.to_string());

    let visitor = if cfg!(feature = "parsing") {
        quote! {
            struct Visitor;
            struct OptionVisitor;

            impl<'a> ::serde::de::Visitor<'a> for Visitor {
                type Value = __TimeSerdeType;

                fn expecting(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
                    write!(
                        f,
                        concat!(
                            "a(n) `",
                            #(ty_s),
                            "` in the format \"{}\"",
                        ),
                        #(format_description_display.as_str())
                    )
                }

                fn visit_str<E: ::serde::de::Error>(
                    self,
                    value: &str
                ) -> Result<__TimeSerdeType, E> {
                    __TimeSerdeType::parse(value, &DESCRIPTION).map_err(E::custom)
                }
            }

            impl<'a> ::serde::de::Visitor<'a> for OptionVisitor {
                type Value = Option<__TimeSerdeType>;

                fn expecting(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
                    write!(
                        f,
                        concat!(
                            "an `Option<",
                            #(ty_s),
                            ">` in the format \"{}\"",
                        ),
                        #(format_description_display.as_str())
                    )
                }

                fn visit_some<D: ::serde::de::Deserializer<'a>>(
                    self,
                    deserializer: D
                ) -> Result<Option<__TimeSerdeType>, D::Error> {
                    deserializer
                        .deserialize_any(Visitor)
                        .map(Some)
                }

                fn visit_none<E: ::serde::de::Error>(
                    self
                ) -> Result<Option<__TimeSerdeType>, E> {
                    Ok(None)
                }
            }
        }
    } else {
        quote!()
    };

    let serialize_primary = if cfg!(feature = "formatting") {
        quote! {
            pub fn serialize<S: ::serde::Serializer>(
                datetime: &__TimeSerdeType,
                serializer: S,
            ) -> Result<S::Ok, S::Error> {
                use ::serde::Serialize;
                datetime
                    .format(&DESCRIPTION)
                    .map_err(::time::error::Format::into_invalid_serde_value::<S>)?
                    .serialize(serializer)
            }
        }
    } else {
        quote!()
    };

    let deserialize_primary = if cfg!(feature = "parsing") {
        quote! {
            pub fn deserialize<'a, D: ::serde::Deserializer<'a>>(
                deserializer: D
            ) -> Result<__TimeSerdeType, D::Error> {
                use ::serde::Deserialize;
                deserializer.deserialize_any(Visitor)
            }
        }
    } else {
        quote!()
    };

    let serialize_option = if cfg!(feature = "formatting") {
        quote! {
            pub fn serialize<S: ::serde::Serializer>(
                option: &Option<__TimeSerdeType>,
                serializer: S,
            ) -> Result<S::Ok, S::Error> {
                use ::serde::Serialize;
                option.map(|datetime| datetime.format(&DESCRIPTION))
                    .transpose()
                    .map_err(::time::error::Format::into_invalid_serde_value::<S>)?
                    .serialize(serializer)
            }
        }
    } else {
        quote!()
    };

    let deserialize_option = if cfg!(feature = "parsing") {
        quote! {
            pub fn deserialize<'a, D: ::serde::Deserializer<'a>>(
                deserializer: D
            ) -> Result<Option<__TimeSerdeType>, D::Error> {
                use ::serde::Deserialize;
                deserializer.deserialize_option(OptionVisitor)
            }
        }
    } else {
        quote!()
    };

    let deserialize_option_imports = if cfg!(feature = "parsing") {
        quote! {
            use super::{OptionVisitor, Visitor};
        }
    } else {
        quote!()
    };

    quote! {
        mod #(mod_name) {
            use ::time::#(ty) as __TimeSerdeType;

            const DESCRIPTION: &[::time::format_description::FormatItem<'_>] = #S(format);

            #S(visitor)
            #S(serialize_primary)
            #S(deserialize_primary)

            pub(super) mod option {
                use super::{DESCRIPTION, __TimeSerdeType};
                #S(deserialize_option_imports)

                #S(serialize_option)
                #S(deserialize_option)
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Robert Clipsham <robert@octarineparrot.com>
//
// 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 libc;

use std::io;
use std::mem;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};

#[cfg(unix)]
#[path = "unix.rs"]
mod imp;

#[cfg(windows)]
#[path = "windows.rs"]
mod imp;

pub use self::imp::public::*;

/// Any file descriptor on unix, only sockets on Windows.
pub struct FileDesc {
    pub fd: CSocket,
}

impl Drop for FileDesc {
    fn drop(&mut self) {
        unsafe {
            close(self.fd);
        }
    }
}

pub fn send_to(socket: CSocket,
               buffer: &[u8],
               dst: *const SockAddr,
               slen: SockLen)
    -> io::Result<usize> {

    let send_len = imp::retry(&mut || unsafe {
        imp::sendto(
            socket,
            buffer.as_ptr() as Buf,
            buffer.len() as BufLen,
            0,
            dst,
            slen
        )
    });

    if send_len < 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(send_len as usize)
    }
}

pub fn recv_from(socket: CSocket,
                 buffer: &mut [u8],
                 caddr: *mut SockAddrStorage)
    -> io::Result<usize> {
    let mut caddrlen = mem::size_of::<SockAddrStorage>() as SockLen;
    let len = imp::retry(&mut || unsafe {
        imp::recvfrom(
            socket,
            buffer.as_ptr() as MutBuf,
            buffer.len() as BufLen,
            0,
            caddr as *mut SockAddr,
            &mut caddrlen
        )
    });

    if len < 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(len as usize)
    }
}

// These functions are taken/adapted from libnative::io::{mod, net}

fn htons(u: u16) -> u16 {
    u.to_be()
}
fn ntohs(u: u16) -> u16 {
    u16::from_be(u)
}

fn make_in6_addr(segments: [u16; 8]) -> In6Addr {
    let mut val: In6Addr = unsafe { mem::uninitialized() };
    val.s6_addr = unsafe {
        mem::transmute([htons(segments[0]),
                        htons(segments[1]),
                        htons(segments[2]),
                        htons(segments[3]),
                        htons(segments[4]),
                        htons(segments[5]),
                        htons(segments[6]),
                        htons(segments[7])])
    };
    val
}

pub fn addr_to_sockaddr(addr: SocketAddr,
                        storage: &mut SockAddrStorage)
    -> SockLen {
    unsafe {
        let len = match addr {
            SocketAddr::V4(sa) => {
                let ip_addr = sa.ip();
                let octets = ip_addr.octets();
                let inaddr = imp::mk_inaddr(u32::from_be(((octets[0] as u32) << 24) |
                                                             ((octets[1] as u32) << 16) |
                                                             ((octets[2] as u32) << 8) |
                                                             (octets[3] as u32)));
                let storage = storage as *mut _ as *mut SockAddrIn;
                (*storage).sin_family = AF_INET as SockAddrFamily;
                (*storage).sin_port = htons(addr.port());
                (*storage).sin_addr = inaddr;
                mem::size_of::<SockAddrIn>()
            }
            SocketAddr::V6(sa) => {
                let ip_addr = sa.ip();
                let segments = ip_addr.segments();
                let inaddr = make_in6_addr(segments);
                let storage = storage as *mut _ as *mut SockAddrIn6;
                (*storage).sin6_family = AF_INET6 as SockAddrFamily6;
                (*storage).sin6_port = htons(addr.port());
                (*storage).sin6_addr = inaddr;
                mem::size_of::<SockAddrIn6>()
            }
        };

        len as SockLen
    }
}

pub fn sockaddr_to_addr(storage: &SockAddrStorage, len: usize) -> io::Result<SocketAddr> {
    match storage.ss_family as libc::c_int {
        AF_INET => {
            assert!(len as usize >= mem::size_of::<SockAddrIn>());
            let storage: &SockAddrIn = unsafe { mem::transmute(storage) };
            let ip = imp::ipv4_addr(storage.sin_addr);
            let a = (ip >> 24) as u8;
            let b = (ip >> 16) as u8;
            let c = (ip >> 8) as u8;
            let d = ip as u8;
            let sockaddrv4 = SocketAddrV4::new(Ipv4Addr::new(a, b, c, d), ntohs(storage.sin_port));
            Ok(SocketAddr::V4(sockaddrv4))
        }
        AF_INET6 => {
            assert!(len as usize >= mem::size_of::<SockAddrIn6>());
            let storage: &SockAddrIn6 = unsafe { mem::transmute(storage) };
            let arr: [u16; 8] = unsafe { mem::transmute(storage.sin6_addr.s6_addr) };
            let a = ntohs(arr[0]);
            let b = ntohs(arr[1]);
            let c = ntohs(arr[2]);
            let d = ntohs(arr[3]);
            let e = ntohs(arr[4]);
            let f = ntohs(arr[5]);
            let g = ntohs(arr[6]);
            let h = ntohs(arr[7]);
            let ip = Ipv6Addr::new(a, b, c, d, e, f, g, h);
            Ok(SocketAddr::V6(SocketAddrV6::new(ip,
                                                ntohs(storage.sin6_port),
                                                u32::from_be(storage.sin6_flowinfo),
                                                u32::from_be(storage.sin6_scope_id))))
        }
        _ => Err(io::Error::new(io::ErrorKind::InvalidData, "expected IPv4 or IPv6 socket")),
    }
}
<commit_msg>pnet_sys: touch up sin6_scope_id use<commit_after>// Copyright (c) 2014 Robert Clipsham <robert@octarineparrot.com>
//
// 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 libc;

use std::io;
use std::mem;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};

#[cfg(unix)]
#[path = "unix.rs"]
mod imp;

#[cfg(windows)]
#[path = "windows.rs"]
mod imp;

pub use self::imp::public::*;

/// Any file descriptor on unix, only sockets on Windows.
pub struct FileDesc {
    pub fd: CSocket,
}

impl Drop for FileDesc {
    fn drop(&mut self) {
        unsafe {
            close(self.fd);
        }
    }
}

pub fn send_to(socket: CSocket,
               buffer: &[u8],
               dst: *const SockAddr,
               slen: SockLen)
    -> io::Result<usize> {

    let send_len = imp::retry(&mut || unsafe {
        imp::sendto(
            socket,
            buffer.as_ptr() as Buf,
            buffer.len() as BufLen,
            0,
            dst,
            slen
        )
    });

    if send_len < 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(send_len as usize)
    }
}

pub fn recv_from(socket: CSocket,
                 buffer: &mut [u8],
                 caddr: *mut SockAddrStorage)
    -> io::Result<usize> {
    let mut caddrlen = mem::size_of::<SockAddrStorage>() as SockLen;
    let len = imp::retry(&mut || unsafe {
        imp::recvfrom(
            socket,
            buffer.as_ptr() as MutBuf,
            buffer.len() as BufLen,
            0,
            caddr as *mut SockAddr,
            &mut caddrlen
        )
    });

    if len < 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(len as usize)
    }
}

// These functions are taken/adapted from libnative::io::{mod, net}

fn htons(u: u16) -> u16 {
    u.to_be()
}
fn ntohs(u: u16) -> u16 {
    u16::from_be(u)
}

fn make_in6_addr(segments: [u16; 8]) -> In6Addr {
    let mut val: In6Addr = unsafe { mem::uninitialized() };
    val.s6_addr = unsafe {
        mem::transmute([htons(segments[0]),
                        htons(segments[1]),
                        htons(segments[2]),
                        htons(segments[3]),
                        htons(segments[4]),
                        htons(segments[5]),
                        htons(segments[6]),
                        htons(segments[7])])
    };
    val
}

pub fn addr_to_sockaddr(addr: SocketAddr,
                        storage: &mut SockAddrStorage)
    -> SockLen {
    unsafe {
        let len = match addr {
            SocketAddr::V4(sa) => {
                let ip_addr = sa.ip();
                let octets = ip_addr.octets();
                let inaddr = imp::mk_inaddr(u32::from_be(((octets[0] as u32) << 24) |
                                                             ((octets[1] as u32) << 16) |
                                                             ((octets[2] as u32) << 8) |
                                                             (octets[3] as u32)));
                let storage = storage as *mut _ as *mut SockAddrIn;
                (*storage).sin_family = AF_INET as SockAddrFamily;
                (*storage).sin_port = htons(addr.port());
                (*storage).sin_addr = inaddr;
                mem::size_of::<SockAddrIn>()
            }
            SocketAddr::V6(sa) => {
                let ip_addr = sa.ip();
                let segments = ip_addr.segments();
                let inaddr = make_in6_addr(segments);
                let storage = storage as *mut _ as *mut SockAddrIn6;
                (*storage).sin6_family = AF_INET6 as SockAddrFamily6;
                (*storage).sin6_port = htons(addr.port());
                (*storage).sin6_addr = inaddr;
                (*storage).sin6_scope_id = sa.scope_id();
                mem::size_of::<SockAddrIn6>()
            }
        };

        len as SockLen
    }
}

pub fn sockaddr_to_addr(storage: &SockAddrStorage, len: usize) -> io::Result<SocketAddr> {
    match storage.ss_family as libc::c_int {
        AF_INET => {
            assert!(len as usize >= mem::size_of::<SockAddrIn>());
            let storage: &SockAddrIn = unsafe { mem::transmute(storage) };
            let ip = imp::ipv4_addr(storage.sin_addr);
            let a = (ip >> 24) as u8;
            let b = (ip >> 16) as u8;
            let c = (ip >> 8) as u8;
            let d = ip as u8;
            let sockaddrv4 = SocketAddrV4::new(Ipv4Addr::new(a, b, c, d), ntohs(storage.sin_port));
            Ok(SocketAddr::V4(sockaddrv4))
        }
        AF_INET6 => {
            assert!(len as usize >= mem::size_of::<SockAddrIn6>());
            let storage: &SockAddrIn6 = unsafe { mem::transmute(storage) };
            let arr: [u16; 8] = unsafe { mem::transmute(storage.sin6_addr.s6_addr) };
            let a = ntohs(arr[0]);
            let b = ntohs(arr[1]);
            let c = ntohs(arr[2]);
            let d = ntohs(arr[3]);
            let e = ntohs(arr[4]);
            let f = ntohs(arr[5]);
            let g = ntohs(arr[6]);
            let h = ntohs(arr[7]);
            let ip = Ipv6Addr::new(a, b, c, d, e, f, g, h);
            Ok(SocketAddr::V6(SocketAddrV6::new(ip,
                                                ntohs(storage.sin6_port),
                                                u32::from_be(storage.sin6_flowinfo),
                                                storage.sin6_scope_id)))
        }
        _ => Err(io::Error::new(io::ErrorKind::InvalidData, "expected IPv4 or IPv6 socket")),
    }
}
<|endoftext|>