1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
#![cfg_attr(feature = "unstable", feature(const_fn, core_intrinsics, drop_types_in_const))]
#![cfg_attr(feature = "serde_macros", feature(custom_derive, plugin))]
#![cfg_attr(feature = "serde_macros", plugin(serde_macros))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(not(feature = "unstable"), deny(warnings))]

extern crate inflector;
#[macro_use]
extern crate lazy_static;
extern crate regex;
extern crate serde;
extern crate serde_json;

#[cfg(not(feature = "serde_macros"))]
extern crate serde_codegen;
#[cfg(not(feature = "serde_macros"))]
extern crate syntex;

use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;

use botocore::Service as BotocoreService;
use generator::generate_source;

mod botocore;
mod generator;

const BOTOCORE_DIR: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/botocore/botocore/data/");

pub struct Service {
    name: String,
    protocol_date: String,
}

impl Service {
    pub fn new<S>(name: S, protocol_date: S) -> Self
        where S: Into<String>
    {
        Service {
            name: name.into(),
            protocol_date: protocol_date.into(),
        }
    }
}

pub fn generate(service: Service, output_path: &Path) {
    let botocore_destination_path = output_path.join(format!("{}_botocore.rs", service.name));
    let serde_destination_path = output_path.join(format!("{}.rs", service.name));
    let botocore_service_data_path = Path::new(BOTOCORE_DIR)
        .join(format!("{}/{}/service-2.json", service.name, service.protocol_date));

    botocore_generate(botocore_service_data_path.as_path(),
                      botocore_destination_path.as_path());
    serde_generate(botocore_destination_path.as_path(),
                   serde_destination_path.as_path());
}

fn botocore_generate(input_path: &Path, output_path: &Path) {
    let mut input_file = File::open(input_path).expect(&format!(
        "{:?} not found",
        input_path,
    ));

    let mut service_data = String::new();

    input_file.read_to_string(&mut service_data).expect(&format!(
        "Failed to read {:?}",
        input_path,
    ));

    let service: BotocoreService = serde_json::from_str(&service_data).expect(&format!(
        "Could not convert JSON in {:?} to Service",
        input_path,
    ));

    let source_code = generate_source(&service);

    let mut output_file = File::create(output_path).expect(&format!(
        "Couldn't open file for writing: {:?}",
        output_path,
    ));

    output_file.write_all(source_code.as_bytes()).expect(&format!(
        "Failed to write generated source code to {:?}",
        output_path,
    ));
}

#[cfg(not(feature = "serde_macros"))]
fn serde_generate(source: &Path, destination: &Path) {
    ::serde_codegen::expand(&source, &destination).unwrap();
}

#[cfg(feature = "serde_macros")]
fn serde_generate(source: &Path, destination: &Path) {
    ::std::fs::copy(source, destination).expect(&format!(
        "Failed to copy {:?} to {:?}",
        source,
        destination,
    ));
}