@@ -8,20 +8,21 @@ use crate::{
8
8
use reqwest:: header;
9
9
use serde:: { Deserialize , Serialize } ;
10
10
use std:: collections:: HashMap ;
11
+ use std:: str:: FromStr ;
11
12
12
13
#[ derive( Debug , Serialize ) ]
13
- struct PlaygroundCode {
14
+ struct PlaygroundCode < ' a > {
14
15
channel : Channel ,
15
16
edition : Edition ,
16
- code : String ,
17
+ code : & ' a str ,
17
18
#[ serde( rename = "crateType" ) ]
18
19
crate_type : CrateType ,
19
20
mode : Mode ,
20
21
tests : bool ,
21
22
}
22
23
23
- impl PlaygroundCode {
24
- fn new ( code : String ) -> Self {
24
+ impl < ' a > PlaygroundCode < ' a > {
25
+ fn new ( code : & ' a str ) -> Self {
25
26
PlaygroundCode {
26
27
channel : Channel :: Nightly ,
27
28
edition : Edition :: E2018 ,
@@ -64,6 +65,19 @@ enum Channel {
64
65
Nightly ,
65
66
}
66
67
68
+ impl FromStr for Channel {
69
+ type Err = Box < dyn std:: error:: Error > ;
70
+
71
+ fn from_str ( s : & str ) -> Result < Self > {
72
+ match s {
73
+ "stable" => Ok ( Channel :: Stable ) ,
74
+ "beta" => Ok ( Channel :: Beta ) ,
75
+ "nightly" => Ok ( Channel :: Nightly ) ,
76
+ _ => Err ( format ! ( "invalid release channel `{}`" , s) . into ( ) ) ,
77
+ }
78
+ }
79
+ }
80
+
67
81
#[ derive( Debug , Serialize ) ]
68
82
enum Edition {
69
83
#[ serde( rename = "2015" ) ]
@@ -72,6 +86,18 @@ enum Edition {
72
86
E2018 ,
73
87
}
74
88
89
+ impl FromStr for Edition {
90
+ type Err = Box < dyn std:: error:: Error > ;
91
+
92
+ fn from_str ( s : & str ) -> Result < Self > {
93
+ match s {
94
+ "2015" => Ok ( Edition :: E2015 ) ,
95
+ "2018" => Ok ( Edition :: E2018 ) ,
96
+ _ => Err ( format ! ( "invalid edition `{}`" , s) . into ( ) ) ,
97
+ }
98
+ }
99
+ }
100
+
75
101
#[ derive( Debug , Serialize ) ]
76
102
enum CrateType {
77
103
#[ serde( rename = "bin" ) ]
@@ -87,6 +113,18 @@ enum Mode {
87
113
Release ,
88
114
}
89
115
116
+ impl FromStr for Mode {
117
+ type Err = Box < dyn std:: error:: Error > ;
118
+
119
+ fn from_str ( s : & str ) -> Result < Self > {
120
+ match s {
121
+ "debug" => Ok ( Mode :: Debug ) ,
122
+ "release" => Ok ( Mode :: Release ) ,
123
+ _ => Err ( format ! ( "invalid compilation mode `{}`" , s) . into ( ) ) ,
124
+ }
125
+ }
126
+ }
127
+
90
128
#[ derive( Debug , Deserialize ) ]
91
129
struct PlayResult {
92
130
success : bool ,
@@ -95,8 +133,32 @@ struct PlayResult {
95
133
}
96
134
97
135
fn run_code ( args : & Args , code : & str ) -> Result < String > {
98
- info ! ( "sending request to playground." ) ;
99
- let request = PlaygroundCode :: new ( code. to_string ( ) ) ;
136
+ let mut errors = String :: new ( ) ;
137
+
138
+ let channel = args. params . get ( "channel" ) . unwrap_or_else ( || & "nightly" ) ;
139
+ let mode = args. params . get ( "mode" ) . unwrap_or_else ( || & "debug" ) ;
140
+ let edition = args. params . get ( "edition" ) . unwrap_or_else ( || & "2018" ) ;
141
+
142
+ let mut request = PlaygroundCode :: new ( code) ;
143
+
144
+ match Channel :: from_str ( channel) {
145
+ Ok ( c) => request. channel = c,
146
+ Err ( e) => errors += & format ! ( "{}\n " , e) ,
147
+ }
148
+
149
+ match Mode :: from_str ( mode) {
150
+ Ok ( m) => request. mode = m,
151
+ Err ( e) => errors += & format ! ( "{}\n " , e) ,
152
+ }
153
+
154
+ match Edition :: from_str ( edition) {
155
+ Ok ( e) => request. edition = e,
156
+ Err ( e) => errors += & format ! ( "{}\n " , e) ,
157
+ }
158
+
159
+ if !code. contains ( "fn main" ) {
160
+ request. crate_type = CrateType :: Library ;
161
+ }
100
162
101
163
let resp = args
102
164
. http
@@ -112,13 +174,16 @@ fn run_code(args: &Args, code: &str) -> Result<String> {
112
174
result. stderr
113
175
} ;
114
176
115
- Ok ( if result. len ( ) > 1994 {
177
+ Ok ( if result. len ( ) + errors . len ( ) > 1994 {
116
178
format ! (
117
- "Output too large. Playground link: {}" ,
179
+ "{}Output too large. Playground link: {}" ,
180
+ errors,
118
181
get_playground_link( args, code, & request) ?
119
182
)
183
+ } else if result. len ( ) == 0 {
184
+ format ! ( "{}compilation succeded." , errors)
120
185
} else {
121
- format ! ( "```{}```" , result)
186
+ format ! ( "{} ```{}```" , errors , result)
122
187
} )
123
188
}
124
189
@@ -134,11 +199,11 @@ fn get_playground_link(args: &Args, code: &str, request: &PlaygroundCode) -> Res
134
199
. send ( ) ?;
135
200
136
201
let resp: HashMap < String , String > = resp. json ( ) ?;
137
- debug ! ( "gist response: {:?}" , resp) ;
202
+ info ! ( "gist response: {:?}" , resp) ;
138
203
139
204
resp. get ( "id" )
140
205
. map ( |id| request. url_from_gist ( id) )
141
- . ok_or ( "no gist found" . into ( ) )
206
+ . ok_or_else ( || "no gist found" . into ( ) )
142
207
}
143
208
144
209
pub fn run ( args : Args ) -> Result < ( ) > {
@@ -152,7 +217,23 @@ pub fn run(args: Args) -> Result<()> {
152
217
Ok ( ( ) )
153
218
}
154
219
155
- pub fn help ( args : Args ) -> Result < ( ) > {
220
+ pub fn help ( args : Args , name : & str ) -> Result < ( ) > {
221
+ let message = format ! (
222
+ "Compile and run rust code. All code is executed on https://play.rust-lang.org.
223
+ ```?{} mode={{}} channel={{}} edition={{}} ``\u{200B} `code``\u{200B} ` ```
224
+ Optional arguments:
225
+ \t mode: debug, release (default: debug)
226
+ \t channel: stable, beta, nightly (default: nightly)
227
+ \t edition: 2015, 2018 (default: 2018)
228
+ " ,
229
+ name
230
+ ) ;
231
+
232
+ api:: send_reply ( & args, & message) ?;
233
+ Ok ( ( ) )
234
+ }
235
+
236
+ pub fn err ( args : Args ) -> Result < ( ) > {
156
237
let message = "Missing code block. Please use the following markdown:
157
238
\\ `\\ `\\ `rust
158
239
code here
@@ -183,7 +264,7 @@ pub fn eval(args: Args) -> Result<()> {
183
264
Ok ( ( ) )
184
265
}
185
266
186
- pub fn eval_help ( args : Args ) -> Result < ( ) > {
267
+ pub fn eval_err ( args : Args ) -> Result < ( ) > {
187
268
let message = "Missing code block. Please use the following markdown:
188
269
\\ `code here\\ `
189
270
or
0 commit comments