diff --git a/Cargo.toml b/Cargo.toml index e6102dc7aa..4ab4a7a429 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,35 +1,8 @@ -# DO NOT PUBLISH -# This library is just to try out the code that should ultimately go into the code generator ! -[package] +[workspace] -name = "client" -version = "0.0.1" -authors = ["Sebastian Thiel "] -description = "A library to facilitate interacting with your youtube account" -repository = "https://github.com/Byron/google-apis-rs" -license = "MIT/Apache-2.0" -keywords = ["youtube", "google", "protocol", "not-for-use"] -edition = "2018" -publish = false - -[lib] -# The common client code, used by all generated implementations -name = "client" -path = "src/rust/lib.rs" - -[dependencies] -google-apis-common = { version = "4.0", path = "google-apis-common" } -clap = "2" -http = "^0.2" -hyper = "0.14" -mime = "0.2" -rustc-serialize = "*" -yup-oauth2 = "^ 7.0" -serde = "1" -serde_json = "1" -serde_derive = "1" -strsim = "*" -tokio = "^ 1.0" -hyper-rustls = "^0.22" -itertools = "^ 0.10" -tower-service = "^0.3" +members = [ + "google-apis-common", + "google-clis-common", + "src/rust/preproc" +] +exclude = ["gen"] \ No newline at end of file diff --git a/google-apis-common/Cargo.toml b/google-apis-common/Cargo.toml index 8c444448ca..d804c70821 100644 --- a/google-apis-common/Cargo.toml +++ b/google-apis-common/Cargo.toml @@ -10,6 +10,8 @@ license = "MIT" keywords = ["google", "web", "api", "common"] edition = "2021" +[lib] +doctest = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -26,4 +28,5 @@ http = "^0.2" tokio = "^1.0" tower-service = "^0.3.1" - +[dev-dependencies] +serde = { version = "^ 1.0", features = ["derive"] } diff --git a/google-apis-common/src/lib.rs b/google-apis-common/src/lib.rs index b593198145..3540fc9b46 100644 --- a/google-apis-common/src/lib.rs +++ b/google-apis-common/src/lib.rs @@ -861,3 +861,71 @@ mod yup_oauth2_impl { } } } + +#[cfg(test)] +mod test_api { + use super::*; + use std::default::Default; + use std::str::FromStr; + + use serde_json as json; + use serde::{Serialize, Deserialize}; + + #[test] + fn serde() { + #[derive(Default, Serialize, Deserialize)] + struct Foo { + opt: Option, + req: u32, + opt_vec: Option>, + vec: Vec, + } + + let f: Foo = Default::default(); + json::to_string(&f).unwrap(); // should work + + let j = "{\"opt\":null,\"req\":0,\"vec\":[]}"; + let _f: Foo = json::from_str(j).unwrap(); + + // This fails, unless 'vec' is optional + // let j = "{\"opt\":null,\"req\":0}"; + // let f: Foo = json::from_str(j).unwrap(); + + #[derive(Default, Serialize, Deserialize)] + struct Bar { + #[serde(rename = "snooSnoo")] + snoo_snoo: String, + } + json::to_string(&::default()).unwrap(); + + let j = "{\"snooSnoo\":\"foo\"}"; + let b: Bar = json::from_str(&j).unwrap(); + assert_eq!(b.snoo_snoo, "foo"); + + // We can't have unknown fields with structs. + // #[derive(Default, Serialize, Deserialize)] + // struct BarOpt { + // #[serde(rename="snooSnoo")] + // snoo_snoo: Option + // } + // let j = "{\"snooSnoo\":\"foo\",\"foo\":\"bar\"}"; + // let b: BarOpt = json::from_str(&j).unwrap(); + } + + #[test] + fn byte_range_from_str() { + assert_eq!( + ::from_str("2-42"), + Ok(Chunk { first: 2, last: 42 }) + ) + } + + #[test] + fn dyn_delegate_is_send() { + fn with_send(_x: impl Send) {} + + let mut dd = DefaultDelegate::default(); + let dlg: &mut dyn Delegate = &mut dd; + with_send(dlg); + } +} diff --git a/google-clis-common/Cargo.toml b/google-clis-common/Cargo.toml new file mode 100644 index 0000000000..33b61d4338 --- /dev/null +++ b/google-clis-common/Cargo.toml @@ -0,0 +1,24 @@ +# DO NOT PUBLISH +# This library is just to try out the code that should ultimately go into the code generator ! +[package] +name = "google-clis-common" +version = "4.0.0" +authors = ["Sebastian Thiel "] +repository = "https://github.com/Byron/google-apis-rs" +homepage = "https://github.com/Byron/google-apis-rs/google-clis-common" +documentation = "https://docs.rs/google-clis-common" +description = "Shared functionality among the google-api CLI crates." +license = "MIT" +keywords = ["google", "web", "api", "cli", "common"] +edition = "2021" + +[lib] +doctest = false + +[dependencies] +mime = "0.2" +yup-oauth2 = "^ 7.0" +serde = "1" +serde_json = "1" +strsim = "*" +clap = "2" diff --git a/src/rust/cli/client.rs b/google-clis-common/src/lib.rs similarity index 93% rename from src/rust/cli/client.rs rename to google-clis-common/src/lib.rs index 1bfb75ccea..f1a74813ea 100644 --- a/src/rust/cli/client.rs +++ b/google-clis-common/src/lib.rs @@ -1,16 +1,15 @@ -use clap::{App, SubCommand}; use mime::Mime; -use crate::oauth2::{ApplicationSecret, ConsoleApplicationSecret}; +use yup_oauth2::{ApplicationSecret, ConsoleApplicationSecret}; use serde_json as json; use serde_json::value::Value; +use clap::arg_enum; use std::env; -use std::error::Error as StdError; use std::fmt; use std::fs; use std::io; -use std::io::{stdout, Read, Write}; -use std::path::{Path, PathBuf}; +use std::io::{stdout, Write}; +use std::path::Path; use std::str::FromStr; use std::string::ToString; @@ -230,7 +229,7 @@ impl FieldCursor { } }; - for (cid, c) in value.chars().enumerate() { + for c in value.chars() { if c == FIELD_SEP { if last_c != FIELD_SEP { push_field(&mut output, &mut field); @@ -370,7 +369,7 @@ pub fn calltype_from_str( ) -> CallType { CallType::Upload(match UploadProtocol::from_str(name) { Ok(up) => up, - Err(msg) => { + Err(_msg) => { err.issues.push(CLIError::InvalidUploadProtocol( name.to_string(), valid_protocols, @@ -744,3 +743,48 @@ pub fn application_secret_from_directory( } unreachable!(); } + + +#[cfg(test)] +mod test_cli { + use super::*; + + use std::default::Default; + + #[test] + fn cursor() { + let mut c: FieldCursor = Default::default(); + + assert_eq!(c.to_string(), ""); + assert_eq!(c.num_fields(), 0); + assert!(c.set("").is_err()); + assert!(c.set(".").is_ok()); + assert!(c.set("..").is_err()); + assert_eq!(c.num_fields(), 0); + + assert!(c.set("foo").is_ok()); + assert_eq!(c.to_string(), "foo"); + assert_eq!(c.num_fields(), 1); + assert!(c.set("..").is_ok()); + assert_eq!(c.num_fields(), 0); + assert_eq!(c.to_string(), ""); + + assert!(c.set("foo.").is_err()); + + assert!(c.set("foo.bar").is_ok()); + assert_eq!(c.num_fields(), 2); + assert_eq!(c.to_string(), "foo.bar"); + assert!(c.set("sub.level").is_ok()); + assert_eq!(c.num_fields(), 4); + assert_eq!(c.to_string(), "foo.bar.sub.level"); + assert!(c.set("...other").is_ok()); + assert_eq!(c.to_string(), "foo.bar.other"); + assert_eq!(c.num_fields(), 3); + assert!(c.set(".one.two.three...beer").is_ok()); + assert_eq!(c.num_fields(), 2); + assert_eq!(c.to_string(), "one.beer"); + assert!(c.set("one.two.three...").is_ok()); + assert_eq!(c.num_fields(), 3); + assert_eq!(c.to_string(), "one.beer.one"); + } +} diff --git a/src/generator/templates/Cargo.toml.mako b/src/generator/templates/Cargo.toml.mako index 584e9755fe..f49e115c6c 100644 --- a/src/generator/templates/Cargo.toml.mako +++ b/src/generator/templates/Cargo.toml.mako @@ -34,7 +34,9 @@ mime = "^ 0.2.0" serde = { version = "^ 1.0", features = ["derive"] } serde_json = "^ 1.0" itertools = "^ 0.10" -% if 'is_executable' not in cargo: +% if cargo.get('is_executable', False): +google-clis-common = { path = "../../google-clis-common", version = "4.0" } +% else: google-apis-common = { path = "../../google-apis-common", version = "4.0" } % endif % for dep in cargo.get('dependencies', list()): diff --git a/src/generator/templates/cli/main.rs.mako b/src/generator/templates/cli/main.rs.mako index c7efb11d65..fcdc9d9108 100644 --- a/src/generator/templates/cli/main.rs.mako +++ b/src/generator/templates/cli/main.rs.mako @@ -14,8 +14,6 @@ #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate tokio; - #[macro_use] extern crate clap; @@ -25,7 +23,7 @@ use clap::{App, SubCommand, Arg}; use ${to_extern_crate_name(library_to_crate_name(library_name(name, version), make.depends_on_suffix))}::{api, Error, oauth2}; -mod client; +use google_clis_common as client; ${engine.new(c)}\ diff --git a/src/generator/templates/deps.mako b/src/generator/templates/deps.mako index 7185757a94..d875a6724d 100644 --- a/src/generator/templates/deps.mako +++ b/src/generator/templates/deps.mako @@ -105,12 +105,9 @@ print('Could not open JSON file at {}'.format(api_json)) print(e) %>\ -${api_common}: $(RUST_SRC)/${make.id}/client.rs $(lastword $(MAKEFILE_LIST)) ${gen_root_stamp} - @ echo "// COPY OF '$<'" > $@ - @ echo "// DO NOT EDIT" >> $@ - @cat $< >> $@ +${api_common}: ${gen_root_stamp} -${gen_root_stamp}: $(MAKO_RENDER) ${' '.join(i[0] for i in sds)} ${api_json_inputs} $(MAKO_STANDARD_DEPENDENCIES) ${depends_on_target} +${gen_root_stamp}: $(MAKO_RENDER) ${' '.join(i[0] for i in sds)} ${api_json_inputs} $(MAKO_STANDARD_DEPENDENCIES) @echo Generating ${api_target} $(MAKO) -io ${' '.join("%s=%s" % (s, d) for s, d in sds)} ${post_processor_arg} --data-files ${api_json_inputs} @touch $@ diff --git a/src/rust/api/client.rs b/src/rust/api/client.rs deleted file mode 100644 index c7ad4dd216..0000000000 --- a/src/rust/api/client.rs +++ /dev/null @@ -1,2 +0,0 @@ -//! This file serves on purpose and is an artifact of the buildsystem. -//! Its content can now be found in the `google-apis-common` crate. \ No newline at end of file diff --git a/src/rust/cli/mod.rs b/src/rust/cli/mod.rs deleted file mode 100644 index b9babe5bc1..0000000000 --- a/src/rust/cli/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod client; diff --git a/src/rust/lib.rs b/src/rust/lib.rs deleted file mode 100644 index 185b0c27b7..0000000000 --- a/src/rust/lib.rs +++ /dev/null @@ -1,153 +0,0 @@ -#![allow( - dead_code, - deprecated, - unused_features, - unused_variables, - unused_imports -)] - -#[macro_use] -extern crate clap; - -#[macro_use] -extern crate hyper; -extern crate mime; -extern crate rustc_serialize; -extern crate serde; -extern crate serde_json; -extern crate yup_oauth2 as oauth2; -#[macro_use] -extern crate serde_derive; -extern crate strsim; - -// just pull it in the check if it compiles -mod cli; -use google_apis_common as api; - -/// This module is for testing only, its code is used in mako templates -#[cfg(test)] -mod test_api { - use super::api::*; - use hyper; - use std::default::Default; - use std::io::Read; - use std::str::FromStr; - - use serde_json as json; - - const EXPECTED: &'static str = "\r\n--MDuXWGyeE33QFXGchb2VFWc4Z7945d\r\n\ -Content-Length: 50\r\n\ -Content-Type: application/json\r\n\ -\r\n\ -foo\r\n\ ---MDuXWGyeE33QFXGchb2VFWc4Z7945d\r\n\ -Content-Length: 25\r\n\ -Content-Type: application/plain\r\n\ -\r\n\ -bar\r\n\ ---MDuXWGyeE33QFXGchb2VFWc4Z7945d--"; - - const EXPECTED_LEN: usize = 223; - - #[test] - fn serde() { - #[derive(Default, Serialize, Deserialize)] - struct Foo { - opt: Option, - req: u32, - opt_vec: Option>, - vec: Vec, - } - - let f: Foo = Default::default(); - json::to_string(&f).unwrap(); // should work - - let j = "{\"opt\":null,\"req\":0,\"vec\":[]}"; - let f: Foo = json::from_str(j).unwrap(); - - // This fails, unless 'vec' is optional - // let j = "{\"opt\":null,\"req\":0}"; - // let f: Foo = json::from_str(j).unwrap(); - - #[derive(Default, Serialize, Deserialize)] - struct Bar { - #[serde(rename = "snooSnoo")] - snoo_snoo: String, - } - json::to_string(&::default()).unwrap(); - - let j = "{\"snooSnoo\":\"foo\"}"; - let b: Bar = json::from_str(&j).unwrap(); - assert_eq!(b.snoo_snoo, "foo"); - - // We can't have unknown fields with structs. - // #[derive(Default, Serialize, Deserialize)] - // struct BarOpt { - // #[serde(rename="snooSnoo")] - // snoo_snoo: Option - // } - // let j = "{\"snooSnoo\":\"foo\",\"foo\":\"bar\"}"; - // let b: BarOpt = json::from_str(&j).unwrap(); - } - - #[test] - fn byte_range_from_str() { - assert_eq!( - ::from_str("2-42"), - Ok(Chunk { first: 2, last: 42 }) - ) - } - - #[test] - fn dyn_delegate_is_send() { - fn with_send(x: impl Send) {} - - let mut dd = DefaultDelegate::default(); - let dlg: &mut dyn Delegate = &mut dd; - with_send(dlg); - } -} - -#[cfg(test)] -mod test_cli { - use super::cli::client::*; - - use std::default::Default; - - #[test] - fn cursor() { - let mut c: FieldCursor = Default::default(); - - assert_eq!(c.to_string(), ""); - assert_eq!(c.num_fields(), 0); - assert!(c.set("").is_err()); - assert!(c.set(".").is_ok()); - assert!(c.set("..").is_err()); - assert_eq!(c.num_fields(), 0); - - assert!(c.set("foo").is_ok()); - assert_eq!(c.to_string(), "foo"); - assert_eq!(c.num_fields(), 1); - assert!(c.set("..").is_ok()); - assert_eq!(c.num_fields(), 0); - assert_eq!(c.to_string(), ""); - - assert!(c.set("foo.").is_err()); - - assert!(c.set("foo.bar").is_ok()); - assert_eq!(c.num_fields(), 2); - assert_eq!(c.to_string(), "foo.bar"); - assert!(c.set("sub.level").is_ok()); - assert_eq!(c.num_fields(), 4); - assert_eq!(c.to_string(), "foo.bar.sub.level"); - assert!(c.set("...other").is_ok()); - assert_eq!(c.to_string(), "foo.bar.other"); - assert_eq!(c.num_fields(), 3); - assert!(c.set(".one.two.three...beer").is_ok()); - assert_eq!(c.num_fields(), 2); - assert_eq!(c.to_string(), "one.beer"); - assert!(c.set("one.two.three...").is_ok()); - assert_eq!(c.num_fields(), 3); - assert_eq!(c.to_string(), "one.beer.one"); - } -} diff --git a/src/rust/preproc/Cargo.toml b/src/rust/preproc/Cargo.toml index 9e1477e0f7..eebc9f668f 100644 --- a/src/rust/preproc/Cargo.toml +++ b/src/rust/preproc/Cargo.toml @@ -5,6 +5,12 @@ authors = ["Sebastian Thiel "] edition = "2018" publish = false +[[bin]] +name = "preproc" +path = "src/main.rs" +doctest = false +test = false + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies]