Skip to content

Commit 2139501

Browse files
committed
upload poisoning survey results
1 parent 9ac2ac2 commit 2139501

File tree

7 files changed

+1105
-0
lines changed

7 files changed

+1105
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target
2+
Cargo.lock
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[package]
2+
name = "poisoning-survey"
3+
version = "0.0.0"
4+
authors = ["KodrAus <[email protected]>"]
5+
edition = "2018"
6+
7+
[[bin]]
8+
name = "poisoning-survey"
9+
path = "main.rs"
10+
11+
[dependencies.csv]
12+
version = "1"
13+
14+
[dependencies.serde_json]
15+
version = "1"
16+
17+
[dependencies.serde_derive]
18+
version = "1"
19+
20+
[dependencies.serde]
21+
version = "1"
22+
23+
[dependencies.time]
24+
version = "0.2"
25+
features = ["serde"]
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Lock Poisoning Survey
2+
3+
Raw results from the [Lock Poisoning Survey](https://blog.rust-lang.org/2020/12/11/lock-poisoning-survey.html) in CSV format. This directory also includes a quick tool to reprocess the raw results into a JSON array for analysis.
4+
5+
All you need is to:
6+
7+
```
8+
cargo run --release
9+
```
10+
11+
from this directory and a JSON array will be emitted to `stdout`.
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
#[macro_use]
2+
extern crate serde_derive;
3+
4+
use std::{fmt, io};
5+
6+
use serde::{
7+
de::{self, Deserializer, Visitor},
8+
ser::Serializer,
9+
};
10+
use time::OffsetDateTime;
11+
12+
#[derive(Debug, Deserialize, Serialize)]
13+
struct Response {
14+
#[serde(rename = "Timestamp")]
15+
#[serde(deserialize_with = "deserialize_timestamp")]
16+
#[serde(serialize_with = "serialize_timestamp")]
17+
timestamp: OffsetDateTime,
18+
19+
#[serde(
20+
rename = "Do you use the standard library’s lock types (Mutex or RwLock) in any of your projects?"
21+
)]
22+
use_stdlib_locks: Option<String>,
23+
24+
#[serde(
25+
rename = "Do you use locks from outside the standard library (such as from antidote or parking_lot) in any of your projects?"
26+
)]
27+
use_non_stdlib_locks: Option<String>,
28+
29+
#[serde(
30+
rename = "Which of these is closest to how you acquire locks? (Select all that apply)"
31+
)]
32+
#[serde(deserialize_with = "deserialize_semi_colon_list")]
33+
#[serde(default)]
34+
acquire_locks: Vec<String>,
35+
36+
#[serde(rename = "Have you ever thought carefully about lock poisoning in your projects?")]
37+
thought_carefully_about_locks: Option<String>,
38+
39+
#[serde(
40+
rename = "If so, what do you want to happen when a lock is poisoned? (Select all that apply)"
41+
)]
42+
#[serde(deserialize_with = "deserialize_semi_colon_list")]
43+
#[serde(default)]
44+
when_lock_is_poisoned: Vec<String>,
45+
46+
#[serde(
47+
rename = "Do you think you’ve benefited from the standard library’s lock types providing poisoning by default?"
48+
)]
49+
benefitted_from_poisoning: Option<String>,
50+
51+
#[serde(
52+
rename = "Do you use the standard library’s lock types or their guards in the public API of any of your projects?"
53+
)]
54+
stdlib_locks_in_pub: Option<String>,
55+
56+
#[serde(
57+
rename = "If so, what’s an example of how the standard library’s lock or guard types appear in the public API of any of your projects? (Please keep accidental information leakage in mind here and consider replacing names with placeholders)"
58+
)]
59+
example_of_stdlib_locks_in_pub: Option<String>,
60+
61+
#[serde(
62+
rename = "How much friction do you think would be involved in migrating any of your projects from the standard library’s poisoning lock types to a non-poisoning lock crate like antidote or parking_lot? (That would mean replacing .lock().unwrap() with .lock())"
63+
)]
64+
friction_in_migrating_from_poisoning: Option<String>,
65+
66+
#[serde(
67+
rename = "Why do you use locks from outside the standard library? (Select all that apply)"
68+
)]
69+
#[serde(deserialize_with = "deserialize_semi_colon_list")]
70+
#[serde(default)]
71+
why_non_stdlib_locks: Vec<String>,
72+
73+
#[serde(rename = "Do you implement poisoning some other way?")]
74+
alt_poisoning_impl: Option<String>,
75+
76+
#[serde(
77+
rename = "If so, what do you want to happen when data is poisoned? (Select all that apply)"
78+
)]
79+
#[serde(deserialize_with = "deserialize_semi_colon_list")]
80+
#[serde(default)]
81+
when_alt_poisoning_is_poisoned: Vec<String>,
82+
83+
#[serde(
84+
rename = "Would you use a poisoning implementation from the standard library if it was independent of Mutex or RwLock?"
85+
)]
86+
use_stdlib_alt_poisoning: Option<String>,
87+
}
88+
89+
fn deserialize_semi_colon_list<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
90+
where
91+
D: Deserializer<'de>,
92+
{
93+
struct SeparatedListVisitor(char);
94+
95+
impl<'de> Visitor<'de> for SeparatedListVisitor {
96+
type Value = Vec<String>;
97+
98+
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
99+
write!(f, "a string of values separated by `{}`", self.0)
100+
}
101+
102+
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
103+
where
104+
E: de::Error,
105+
{
106+
if v.is_empty() {
107+
return Ok(Vec::new());
108+
}
109+
110+
Ok(v.split(self.0).map(|v| v.to_owned()).collect())
111+
}
112+
}
113+
114+
deserializer.deserialize_str(SeparatedListVisitor(';'))
115+
}
116+
117+
fn deserialize_timestamp<'de, D>(deserializer: D) -> Result<OffsetDateTime, D::Error>
118+
where
119+
D: Deserializer<'de>,
120+
{
121+
struct TimestampVisitor;
122+
123+
impl<'de> Visitor<'de> for TimestampVisitor {
124+
type Value = OffsetDateTime;
125+
126+
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
127+
write!(f, "a timestamp string")
128+
}
129+
130+
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
131+
where
132+
E: de::Error,
133+
{
134+
let mut parts = v.split("GMT");
135+
let dt = parts
136+
.next()
137+
.ok_or_else(|| E::custom("missing datetime part of timestamp"))?
138+
.trim();
139+
let offset = parts
140+
.next()
141+
.ok_or_else(|| E::custom("missing offset part of timestamp"))?
142+
.trim();
143+
144+
let dt = time::PrimitiveDateTime::parse(dt, "%Y/%m/%d %-I:%M:%S %P")
145+
.map_err(|e| E::custom(e))?;
146+
147+
Ok(dt.assume_offset(time::UtcOffset::hours({
148+
if offset.starts_with("+") {
149+
&offset[1..]
150+
} else {
151+
offset
152+
}
153+
.parse()
154+
.map_err(|e| E::custom(e))
155+
}?)))
156+
}
157+
}
158+
159+
deserializer.deserialize_str(TimestampVisitor)
160+
}
161+
162+
fn serialize_timestamp<S>(value: &OffsetDateTime, serializer: S) -> Result<S::Ok, S::Error>
163+
where
164+
S: Serializer,
165+
{
166+
serializer.collect_str(&value.lazy_format("%Y-%0m-%0dT%0H:%0M:%0S%z"))
167+
}
168+
169+
fn main() {
170+
let results = csv::ReaderBuilder::new()
171+
.from_path("poisoning-survey.csv")
172+
.expect("failed to create csv reader over results file")
173+
.deserialize()
174+
.map(|row| row.expect("failed to deserialize a row"))
175+
.collect::<Vec<Response>>();
176+
177+
let stdout = io::stdout();
178+
serde_json::to_writer(stdout.lock(), &results).expect("failed to write JSON");
179+
}

0 commit comments

Comments
 (0)