Skip to content

Commit

Permalink
Implement simple JSON serializer (#411)
Browse files Browse the repository at this point in the history
* Implement simple JSON serializer

* CR feedback

* Add debug assertion to `append_string_unchecked`
  • Loading branch information
jdisanti authored May 25, 2021
1 parent b18421d commit 2b072e0
Show file tree
Hide file tree
Showing 6 changed files with 530 additions and 1 deletion.
2 changes: 1 addition & 1 deletion aws/sdk/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ plugins {
val smithyVersion: String by project

val sdkOutputDir = buildDir.resolve("aws-sdk")
val runtimeModules = listOf("smithy-types", "smithy-xml", "smithy-http", "smithy-http-tower", "protocol-test-helpers")
val runtimeModules = listOf("smithy-types", "smithy-json", "smithy-xml", "smithy-http", "smithy-http-tower", "protocol-test-helpers")
val awsModules = listOf("aws-auth", "aws-endpoint", "aws-types", "aws-hyper", "aws-sig-auth", "aws-http")

buildscript {
Expand Down
1 change: 1 addition & 0 deletions rust-runtime/inlineable/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ are to allow this crate to be compilable and testable in isolation, no client co
"http" = "0.2.1"
"smithy-types" = { version = "0.0.1", path = "../smithy-types" }
"smithy-http" = { version = "0.0.1", path = "../smithy-http" }
"smithy-json" = { path = "../smithy-json" }
"smithy-xml" = { path = "../smithy-xml" }
"fastrand" = "1"

Expand Down
14 changes: 14 additions & 0 deletions rust-runtime/smithy-json/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "smithy-json"
version = "0.1.0"
authors = ["AWS Rust SDK Team <aws-sdk-rust@amazon.com>", "John DiSanti <jdisanti@amazon.com>"]
edition = "2018"

[dependencies]
itoa = "0.4"
ryu = "1.0"
smithy-types = { path = "../smithy-types" }

[dev-dependencies]
proptest = "1"
serde_json = "1.0"
68 changes: 68 additions & 0 deletions rust-runtime/smithy-json/src/escape.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/

use std::borrow::Cow;

const ESCAPES: &[char] = &['"', '\\', '\u{08}', '\u{0C}', '\n', '\r', '\t'];

/// Escapes a string for embedding in a JSON string value.
pub fn escape_string(value: &str) -> Cow<str> {
if !value.contains(ESCAPES) {
return Cow::Borrowed(value);
}

let mut escaped = String::new();
let (mut last, end) = (0, value.len());
for (index, chr) in value
.char_indices()
.filter(|(_index, chr)| ESCAPES.contains(chr))
{
escaped.push_str(&value[last..index]);
escaped.push_str(match chr {
'"' => "\\\"",
'\\' => "\\\\",
'\u{08}' => "\\b",
'\u{0C}' => "\\f",
'\n' => "\\n",
'\r' => "\\r",
'\t' => "\\t",
_ => unreachable!(),
});
last = index + 1;
}
escaped.push_str(&value[last..end]);
Cow::Owned(escaped)
}

#[cfg(test)]
mod test {
use super::escape_string;

#[test]
fn escape() {
assert_eq!("", escape_string("").as_ref());
assert_eq!("foo", escape_string("foo").as_ref());
assert_eq!("foo\\r\\n", escape_string("foo\r\n").as_ref());
assert_eq!("foo\\r\\nbar", escape_string("foo\r\nbar").as_ref());
assert_eq!(r#"foo\\bar"#, escape_string(r#"foo\bar"#).as_ref());
assert_eq!(r#"\\foobar"#, escape_string(r#"\foobar"#).as_ref());
assert_eq!(
r#"\bf\fo\to\r\n"#,
escape_string("\u{08}f\u{0C}o\to\r\n").as_ref()
);
assert_eq!("\\\"test\\\"", escape_string("\"test\"").as_ref());
}

use proptest::proptest;
proptest! {
#[test]
fn matches_serde_json(s: String) {
assert_eq!(
serde_json::to_string(&s).unwrap(),
format!(r#""{}""#, escape_string(&s))
)
}
}
}
9 changes: 9 additions & 0 deletions rust-runtime/smithy-json/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/

//! JSON Abstractions for Smithy

mod escape;
pub mod serialize;
Loading

0 comments on commit 2b072e0

Please sign in to comment.