in sdk/cosmos/azure_data_cosmos/src/partition_key.rs [102:154]
fn as_headers(&self) -> Result<Self::Iter, Self::Error> {
// We have to do some manual JSON serialization here.
// The partition key is sent in an HTTP header, when used to set the partition key for a query.
// It's not safe to use non-ASCII characters in HTTP headers, and serde_json will not escape non-ASCII characters if they are otherwise valid as UTF-8.
// So, we do some conversion by hand, with the help of Rust's own `encode_utf16` method which gives us the necessary code points for non-ASCII values, and produces surrogate pairs as needed.
let mut json = String::new();
let mut utf_buf = [0; 2]; // A buffer for encoding UTF-16 characters.
json.push('[');
for key in &self.0 {
match key.0 {
InnerPartitionKeyValue::Null => json.push_str("null"),
InnerPartitionKeyValue::String(ref string_key) => {
json.push('"');
for char in string_key.chars() {
match char {
'\x08' => json.push_str(r#"\b"#),
'\x0c' => json.push_str(r#"\f"#),
'\n' => json.push_str(r#"\n"#),
'\r' => json.push_str(r#"\r"#),
'\t' => json.push_str(r#"\t"#),
'"' => json.push_str(r#"\""#),
'\\' => json.push('\\'),
c if c.is_ascii() => json.push(c),
c => {
let encoded = c.encode_utf16(&mut utf_buf);
for code_unit in encoded {
json.push_str(&format!(r#"\u{:04x}"#, code_unit));
}
}
}
}
json.push('"');
}
InnerPartitionKeyValue::Number(ref num) => {
json.push_str(
serde_json::to_string(&serde_json::Value::Number(num.clone()))?.as_str(),
);
}
}
json.push(',');
}
// Pop the trailing ','
json.pop();
json.push(']');
Ok(std::iter::once((
constants::PARTITION_KEY,
HeaderValue::from_cow(json),
)))
}