-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
8,516 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/target | ||
**/*.rs.bk | ||
Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
language: rust | ||
cache: cargo | ||
sudo: required | ||
dist: trusty | ||
addons: | ||
apt: | ||
packages: | ||
- libcurl4-openssl-dev | ||
- libelf-dev | ||
- libdw-dev | ||
|
||
rust: | ||
- stable | ||
- beta | ||
- nightly | ||
|
||
before_script: | ||
- | | ||
pip install 'travis-cargo<0.2' --user && | ||
cargo uninstall semantic-rs ; | ||
cargo install --git https://github.com/semantic-rs/semantic-rs --debug && | ||
export PATH=$HOME/.cargo/bin:$PATH && | ||
export RUST_BACKTRACE=1 && | ||
git config --global user.name semantic-rs && | ||
git config --global user.email semantic@rs | ||
script: | ||
- | | ||
travis-cargo build && | ||
travis-cargo test && | ||
travis-cargo --only stable doc | ||
after_success: | ||
- | | ||
RUST_LOG=debug semantic-rs | ||
env: | ||
global: | ||
- TRAVIS_CARGO_NIGHTLY_FEATURE="" | ||
- secure: "AQTT6qOldyg/PkS/mXwhbTcrlGI9q0no5Ucgd4P2ndpRr3GWwPx4ZppOHHO65HKxQMtmWOp1+sUsyVsekiOitB9TtmmVWEMotzTmmH0KIoZ6EzH9M3X/qOe1vEeHDkWceO8VpFOBbnwQb+q8FBgzCnmo+lypLrbHjqtiVKe41HDusP7lqGo+1yWhzg3IGWhbHBYIJ/v5pMNwLW7xbJgVsoLAucklPv4n/eWPP8FR7KculDKWxKNJCJ9Xa+/Bdq8sPI7zhnv+CzxuTozim49elUvugH+G7QleVtbrnIklnc71Bvne3MN7LJL8yr0p+F+HrdqAKsNQhjVd0CQfTa3r2OVLAz30mt7lPBS8kYY2/zDM3eMP4gGTH3jXg5NT3qOcKdc9yzDov0/lTaRlPEBTepdCeBN8oPpXNXV+CMSGE1Qi3xlLuU6UUW+LKZRSSlPA/u4IDLdxRdZ+qbIDvWnjAcBt9jd10PfYtxRhPwwCH0ODA2l3EMBNBcHrR8Ss84yazYnP+5c0fZ6gmgRXCGjCS88mXJnCZWlu2xXscd7wvZwKXCHB0f2bLfqKLuKIZs/EQc+VX8iiekEfEN6AIdb+fxd2YR5TWRK9Zlr9tdRNBCXA95MgQ9nRe+HJh7zV3jwIjCzHF7dBcw5lH8GFA3FmYX1xiCXMcH3HWdGkhAVOMvU=" | ||
- secure: "JmO3fOavkOMn0JnpiS8v6HaW/R+u/npFYMB2NrB8emL7/y5BvTEbYRv+faXcVcVmW1p+AkJxiawaDl7q2WD34JVEE4IWsIVHTjqRj8NJE70miOt36dIR0Fuwl1wNUcYMqNAlzkOaHrajrJ1AYO/HtzZXN8NDtlKgaFwxmJFRURuygQAYFAHW0qR1oyaYEtENU4xumn9i2tlYMln3YAc/aMfy3IcgBcgmfw2M34MCypifrf/OOvpoFbwSVdTT0wwD5rD95YF8qC/X7gCF4YIwH5DQPLw6NJaKeCEkwzlxfwFOKN3/rJt1bMK2bPP9x/LkeRM12jjUQkTWH/iTMtlEQ2oE4nUC3CbexX+hKYNpW7GT21W+q6gfxnsKTSGfbmSWjfYWOHFmcTtCksVsNj7PnbaCxTNPl2xhSOLiPPyWl+nJ1/NUiebUUosl+GCNOmcN1MR4ii57UubnjfNTjmKdx+sIyPgF0CGlJc+CLiDAFIQwVE1fbykaKJXdyISGTHeLBCnmCm0mM3bqyuXgsCqK61PxmR3fPouJ16TJ8/8gswXhg2r+Uoq45nycwbHgwcLnN7aSBlbuRbhx3xr+SUf6Vw5vwEhxXiMGZN9E5pvTMznDedPZtyHGcgXI/A0bif1Kr25IK3+d2a2yyp+EWcDQ2toNqLMjEJ0Q6C+CwF+f/I4=" | ||
|
||
notifications: | ||
email: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
[package] | ||
name = "postman_collection" | ||
version = "0.0.0" | ||
authors = ["Sebastian Mandrean <[email protected]>"] | ||
description = "A Postman Collection serialization & deserialization library." | ||
license = "MIT" | ||
repository = "https://github.com/mandrean/postman-collection-rs" | ||
documentation = "https://docs.rs/postman_collection" | ||
readme = "README.md" | ||
keywords = ["postman", "collection", "postman-collection", "serialization", "deserialization"] | ||
|
||
[badges] | ||
travis-ci = { repository = "mandrean/postman-collection-rs" } | ||
|
||
[dependencies] | ||
error-chain = "0.12" | ||
serde = "1.0" | ||
serde_derive = "1.0" | ||
serde_json = { version = "1.0", features = ["raw_value"] } | ||
serde_yaml = "0.8" | ||
semver = "0.9" | ||
url = "1.7" | ||
url_serde = "0.2" | ||
|
||
[dev-dependencies] | ||
glob = "0.2" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,45 @@ | ||
postman-collection-rs | ||
===================== | ||
[Postman Collection][postman_collection] serializing & deserializing library, written purely in Rust. | ||
[Postman Collection][postman_collection] serialization & deserialization library, written in Rust. | ||
|
||
[![Build Status](https://travis-ci.org/mandrean/postman-collection-rs.svg?branch=master)](https://travis-ci.org/mandrean/postman-collection-rs) | ||
[![Latest version](https://img.shields.io/crates/v/postman_collection.svg)](https://crates.io/crates/postman_collection) | ||
[![Documentation](https://docs.rs/postman_collection/badge.svg)](https://docs.rs/postman_collection) | ||
![License](https://img.shields.io/crates/l/postman_collection.svg) | ||
|
||
Install | ||
------- | ||
Add the following to your `Cargo.toml` file: | ||
|
||
```toml | ||
[dependencies] | ||
postman_collection = "0.1" | ||
``` | ||
|
||
Use | ||
--- | ||
```rust | ||
extern crate postman_collection; | ||
|
||
fn main() { | ||
match postman_collection::from_path("path/to/postman-collection.json") { | ||
Ok(spec) => println!("spec: {:?}", spec), | ||
Err(err) => println!("error: {}", err) | ||
} | ||
} | ||
``` | ||
|
||
See [examples/printer.rs](examples/printer.rs) for more. | ||
|
||
Contribute | ||
---------- | ||
This project follows [semver], [conventional commits] and semantic releasing using [semantic-rs]. | ||
|
||
Note | ||
---- | ||
Inspired by [softprops/openapi](https://github.com/softprops/openapi). | ||
|
||
[postman_collection]: https://www.getpostman.com/collection | ||
[semver]: https://semver.org/ | ||
[conventional commits]: https://www.conventionalcommits.org | ||
[semantic-rs]: https://github.com/semantic-rs/semantic-rs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
extern crate postman_collection; | ||
|
||
use postman_collection::PostmanCollection; | ||
use std::io::Write; | ||
|
||
fn main() { | ||
if let Some(path) = std::env::args().nth(1) { | ||
match postman_collection::from_path(path) { | ||
Ok(collection) => { | ||
match collection { | ||
PostmanCollection::V1_0_0(spec) => { | ||
println!("Found v1.0.0 collection with the name: {}", spec.name); | ||
} | ||
PostmanCollection::V2_0_0(spec) => { | ||
println!("Found v2.0.0 collection with the name: {}", spec.info.name); | ||
} | ||
PostmanCollection::V2_1_0(spec) => { | ||
println!("Found v2.1.0 collection with the name: {}", spec.info.name); | ||
} | ||
} | ||
//println!("{}", postman_collection::to_json(&spec).unwrap()); | ||
} | ||
Err(e) => { | ||
let stderr = &mut ::std::io::stderr(); | ||
let errmsg = "Error writing to stderr"; | ||
|
||
writeln!(stderr, "error: {}", e).expect(errmsg); | ||
|
||
for e in e.iter().skip(1) { | ||
writeln!(stderr, "caused by: {}", e).expect(errmsg); | ||
} | ||
|
||
// The backtrace is not always generated. Try to run this example | ||
// with `RUST_BACKTRACE=1`. | ||
if let Some(backtrace) = e.backtrace() { | ||
writeln!(stderr, "backtrace: {:?}", backtrace).expect(errmsg); | ||
} | ||
|
||
::std::process::exit(1); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,226 @@ | ||
#[macro_use] | ||
extern crate error_chain; | ||
#[macro_use] | ||
extern crate serde_derive; | ||
#[cfg(test)] | ||
extern crate glob; | ||
extern crate semver; | ||
extern crate serde; | ||
extern crate serde_json; | ||
extern crate serde_yaml; | ||
extern crate url; | ||
extern crate url_serde; | ||
|
||
use std::fs::File; | ||
use std::io::Read; | ||
use std::path::Path; | ||
|
||
pub mod v1_0_0; | ||
pub mod v2_0_0; | ||
pub mod v2_1_0; | ||
pub use errors::{Result, ResultExt}; | ||
|
||
const MINIMUM_POSTMAN_COLLECTION_VERSION: &str = ">= 1.0.0"; | ||
|
||
/// Errors that Postman Collection functions may return | ||
pub mod errors { | ||
error_chain! { | ||
foreign_links { | ||
Io(::std::io::Error); | ||
Yaml(::serde_yaml::Error); | ||
Serialize(::serde_json::Error); | ||
SemVerError(::semver::SemVerError); | ||
} | ||
|
||
errors { | ||
UnsupportedSpecFileVersion(version: ::semver::Version) { | ||
description("Unsupported Postman Collection file version") | ||
display("Unsupported Postman Collection file version ({}). Expected {}", version, ::MINIMUM_POSTMAN_COLLECTION_VERSION) | ||
} | ||
} | ||
} | ||
} | ||
|
||
/// Supported versions of Postman Collection. | ||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] | ||
#[serde(untagged)] | ||
pub enum PostmanCollection { | ||
/// Version 1.0.0 of the Postman Collection specification. | ||
/// | ||
/// Refer to the official | ||
/// [specification](https://schema.getpostman.com/collection/json/v1.0.0/draft-07/docs/index.html) | ||
/// for more information. | ||
#[allow(non_camel_case_types)] | ||
V1_0_0(v1_0_0::Spec), | ||
/// Version 1.0.0 of the Postman Collection specification. | ||
/// | ||
/// Refer to the official | ||
/// [specification](https://schema.getpostman.com/collection/json/v2.0.0/draft-07/docs/index.html) | ||
/// for more information. | ||
#[allow(non_camel_case_types)] | ||
V2_0_0(v2_0_0::Spec), | ||
/// Version 1.0.0 of the Postman Collection specification. | ||
/// | ||
/// Refer to the official | ||
/// [specification](https://schema.getpostman.com/collection/json/v2.1.0/draft-07/docs/index.html) | ||
/// for more information. | ||
#[allow(non_camel_case_types)] | ||
V2_1_0(v2_1_0::Spec), | ||
} | ||
|
||
/// Deserialize a Postman Collection from a path | ||
pub fn from_path<P>(path: P) -> errors::Result<PostmanCollection> | ||
where | ||
P: AsRef<Path>, | ||
{ | ||
from_reader(File::open(path)?) | ||
} | ||
|
||
/// Deserialize a Postman Collection from type which implements Read | ||
pub fn from_reader<R>(read: R) -> errors::Result<PostmanCollection> | ||
where | ||
R: Read, | ||
{ | ||
Ok(serde_yaml::from_reader::<R, PostmanCollection>(read)?) | ||
} | ||
|
||
/// Serialize Postman Collection spec to a YAML string | ||
pub fn to_yaml(spec: &PostmanCollection) -> errors::Result<String> { | ||
Ok(serde_yaml::to_string(spec)?) | ||
} | ||
|
||
/// Serialize Postman Collection spec to JSON string | ||
pub fn to_json(spec: &PostmanCollection) -> errors::Result<String> { | ||
Ok(serde_json::to_string_pretty(spec)?) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use glob::glob; | ||
use std::fs::File; | ||
use std::io::Write; | ||
|
||
/// Helper function for reading a file to string. | ||
fn read_file<P>(path: P) -> String | ||
where | ||
P: AsRef<Path>, | ||
{ | ||
let mut f = File::open(path).unwrap(); | ||
let mut content = String::new(); | ||
f.read_to_string(&mut content).unwrap(); | ||
content | ||
} | ||
|
||
/// Helper function to write string to file. | ||
fn write_to_file<P>(path: P, filename: &str, data: &str) | ||
where | ||
P: AsRef<Path> + std::fmt::Debug, | ||
{ | ||
println!(" Saving string to {:?}...", path); | ||
std::fs::create_dir_all(&path).unwrap(); | ||
let full_filename = path.as_ref().to_path_buf().join(filename); | ||
let mut f = File::create(&full_filename).unwrap(); | ||
f.write_all(data.as_bytes()).unwrap(); | ||
} | ||
|
||
/// Convert a YAML `&str` to a JSON `String`. | ||
fn convert_yaml_str_to_json(yaml_str: &str) -> String { | ||
let yaml: serde_yaml::Value = serde_yaml::from_str(yaml_str).unwrap(); | ||
let json: serde_json::Value = serde_yaml::from_value(yaml).unwrap(); | ||
serde_json::to_string_pretty(&json).unwrap() | ||
} | ||
|
||
/// Deserialize and re-serialize the input file to a JSON string through two different | ||
/// paths, comparing the result. | ||
/// 1. File -> `String` -> `serde_yaml::Value` -> `serde_json::Value` -> `String` | ||
/// 2. File -> `Spec` -> `serde_json::Value` -> `String` | ||
/// Both conversion of `serde_json::Value` -> `String` are done | ||
/// using `serde_json::to_string_pretty`. | ||
/// Since the first conversion is independent of the current crate (and only | ||
/// uses serde's json and yaml support), no information should be lost in the final | ||
/// JSON string. The second conversion goes through our `PostmanCollection`, so the final JSON | ||
/// string is a representation of _our_ implementation. | ||
/// By comparing those two JSON conversions, we can validate our implementation. | ||
fn compare_spec_through_json( | ||
input_file: &Path, | ||
save_path_base: &Path, | ||
) -> (String, String, String) { | ||
// First conversion: | ||
// File -> `String` -> `serde_yaml::Value` -> `serde_json::Value` -> `String` | ||
|
||
// Read the original file to string | ||
let spec_yaml_str = read_file(&input_file); | ||
// Convert YAML string to JSON string | ||
let spec_json_str = convert_yaml_str_to_json(&spec_yaml_str); | ||
|
||
// Second conversion: | ||
// File -> `Spec` -> `serde_json::Value` -> `String` | ||
|
||
// Parse the input file | ||
let parsed_spec = from_path(&input_file).unwrap(); | ||
// Convert to serde_json::Value | ||
let parsed_spec_json: serde_json::Value = serde_json::to_value(parsed_spec).unwrap(); | ||
// Convert to a JSON string | ||
let parsed_spec_json_str: String = serde_json::to_string_pretty(&parsed_spec_json).unwrap(); | ||
|
||
// Save JSON strings to file | ||
let api_filename = input_file | ||
.file_name() | ||
.unwrap() | ||
.to_str() | ||
.unwrap() | ||
.replace(".yaml", ".json"); | ||
|
||
let mut save_path = save_path_base.to_path_buf(); | ||
save_path.push("yaml_to_json"); | ||
write_to_file(&save_path, &api_filename, &spec_json_str); | ||
|
||
let mut save_path = save_path_base.to_path_buf(); | ||
save_path.push("yaml_to_spec_to_json"); | ||
write_to_file(&save_path, &api_filename, &parsed_spec_json_str); | ||
|
||
// Return the JSON filename and the two JSON strings | ||
(api_filename, parsed_spec_json_str, spec_json_str) | ||
} | ||
|
||
// Just tests if the deserialization does not blow up. But does not test correctness | ||
#[test] | ||
fn can_deserialize() { | ||
for entry in glob("/tests/fixtures/collection/*.json").expect("Failed to read glob pattern") { | ||
let entry = entry.unwrap(); | ||
let path = entry.as_path(); | ||
// cargo test -- --nocapture to see this message | ||
println!("Testing if {:?} is deserializable", path); | ||
from_path(path).unwrap(); | ||
} | ||
} | ||
|
||
#[test] | ||
fn can_deserialize_and_reserialize() { | ||
let save_path_base: std::path::PathBuf = | ||
["target", "tests", "can_deserialize_and_reserialize"] | ||
.iter() | ||
.collect(); | ||
let mut invalid_diffs = Vec::new(); | ||
|
||
for entry in glob("/tests/fixtures/collection/*.json").expect("Failed to read glob pattern") { | ||
let entry = entry.unwrap(); | ||
let path = entry.as_path(); | ||
|
||
println!("Testing if {:?} is deserializable", path); | ||
|
||
let (api_filename, parsed_spec_json_str, spec_json_str) = | ||
compare_spec_through_json(&path, &save_path_base); | ||
|
||
if parsed_spec_json_str != spec_json_str { | ||
invalid_diffs.push((api_filename, parsed_spec_json_str, spec_json_str)); | ||
} | ||
} | ||
|
||
for invalid_diff in &invalid_diffs { | ||
println!("File {} failed JSON comparison!", invalid_diff.0); | ||
} | ||
assert_eq!(invalid_diffs.len(), 0); | ||
} | ||
} |
Oops, something went wrong.