Skip to content

Commit 85baac0

Browse files
authored
Improve http-client example. (#122)
1 parent 79e29ee commit 85baac0

File tree

5 files changed

+36
-32
lines changed

5 files changed

+36
-32
lines changed

examples/http-client/src/client.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,21 @@
88
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
99
// See the Mulan PSL v2 for more details.
1010

11-
use crate::{errors::HttpClientError, request::REQUEST_BUILDER_CLASS_NAME};
11+
use crate::{errors::HttpClientError, request::REQUEST_BUILDER_CLASS};
1212
use phper::{
1313
alloc::ToRefOwned,
14-
classes::{ClassEntity, ClassEntry, Visibility},
14+
classes::{ClassEntity, StateClass, Visibility},
1515
functions::Argument,
1616
};
1717
use reqwest::blocking::{Client, ClientBuilder};
1818
use std::{convert::Infallible, mem::take, time::Duration};
1919

2020
const HTTP_CLIENT_BUILDER_CLASS_NAME: &str = "HttpClient\\HttpClientBuilder";
21+
2122
const HTTP_CLIENT_CLASS_NAME: &str = "HttpClient\\HttpClient";
2223

24+
static HTTP_CLIENT_CLASS: StateClass<Option<Client>> = StateClass::null();
25+
2326
pub fn make_client_builder_class() -> ClassEntity<ClientBuilder> {
2427
// `new_with_default_state_constructor` means initialize the state of
2528
// `ClientBuilder` as `Default::default`.
@@ -52,11 +55,8 @@ pub fn make_client_builder_class() -> ClassEntity<ClientBuilder> {
5255
class.add_method("build", Visibility::Public, |this, _arguments| {
5356
let state = take(this.as_mut_state());
5457
let client = ClientBuilder::build(state).map_err(HttpClientError::Reqwest)?;
55-
let class = ClassEntry::from_globals(HTTP_CLIENT_CLASS_NAME)?;
56-
let mut object = class.init_object()?;
57-
unsafe {
58-
*object.as_mut_state_obj().as_mut_state() = Some(client);
59-
}
58+
let mut object = HTTP_CLIENT_CLASS.init_object()?;
59+
*object.as_mut_state() = Some(client);
6060
Ok::<_, phper::Error>(object)
6161
});
6262

@@ -67,6 +67,8 @@ pub fn make_client_class() -> ClassEntity<Option<Client>> {
6767
let mut class =
6868
ClassEntity::<Option<Client>>::new_with_default_state_constructor(HTTP_CLIENT_CLASS_NAME);
6969

70+
class.bind(&HTTP_CLIENT_CLASS);
71+
7072
class.add_method("__construct", Visibility::Private, |_, _| {
7173
Ok::<_, Infallible>(())
7274
});
@@ -76,10 +78,8 @@ pub fn make_client_class() -> ClassEntity<Option<Client>> {
7678
let url = arguments[0].expect_z_str()?.to_str().unwrap();
7779
let client = this.as_state().as_ref().unwrap();
7880
let request_builder = client.get(url);
79-
let mut object = ClassEntry::from_globals(REQUEST_BUILDER_CLASS_NAME)?.init_object()?;
80-
unsafe {
81-
*object.as_mut_state_obj().as_mut_state() = Some(request_builder);
82-
}
81+
let mut object = REQUEST_BUILDER_CLASS.init_object()?;
82+
*object.as_mut_state() = Some(request_builder);
8383
Ok::<_, phper::Error>(object)
8484
})
8585
.argument(Argument::by_val("url"));
@@ -89,10 +89,8 @@ pub fn make_client_class() -> ClassEntity<Option<Client>> {
8989
let url = arguments[0].expect_z_str()?.to_str().unwrap();
9090
let client = this.as_state().as_ref().unwrap();
9191
let request_builder = client.post(url);
92-
let mut object = ClassEntry::from_globals(REQUEST_BUILDER_CLASS_NAME)?.init_object()?;
93-
unsafe {
94-
*object.as_mut_state_obj().as_mut_state() = Some(request_builder);
95-
}
92+
let mut object = REQUEST_BUILDER_CLASS.init_object()?;
93+
*object.as_mut_state() = Some(request_builder);
9694
Ok::<_, phper::Error>(object)
9795
})
9896
.argument(Argument::by_val("url"));

examples/http-client/src/request.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,31 @@
88
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
99
// See the Mulan PSL v2 for more details.
1010

11-
use crate::{errors::HttpClientError, response::RESPONSE_CLASS_NAME};
12-
use phper::{
13-
classes::{ClassEntity, ClassEntry, Visibility},
14-
errors::ThrowObject,
15-
};
11+
use crate::{errors::HttpClientError, response::RESPONSE_CLASS};
12+
use phper::classes::{ClassEntity, StateClass, Visibility};
1613
use reqwest::blocking::RequestBuilder;
1714
use std::{convert::Infallible, mem::take};
1815

1916
pub const REQUEST_BUILDER_CLASS_NAME: &str = "HttpClient\\RequestBuilder";
2017

18+
pub static REQUEST_BUILDER_CLASS: StateClass<Option<RequestBuilder>> = StateClass::null();
19+
2120
pub fn make_request_builder_class() -> ClassEntity<Option<RequestBuilder>> {
2221
let mut class = ClassEntity::<Option<RequestBuilder>>::new_with_default_state_constructor(
2322
REQUEST_BUILDER_CLASS_NAME,
2423
);
2524

25+
class.bind(&REQUEST_BUILDER_CLASS);
26+
2627
class.add_method("__construct", Visibility::Private, |_, _| {
2728
Ok::<_, Infallible>(())
2829
});
2930

3031
class.add_method("send", Visibility::Public, |this, _arguments| {
3132
let state = take(this.as_mut_state());
3233
let response = state.unwrap().send().map_err(HttpClientError::Reqwest)?;
33-
let mut object = ClassEntry::from_globals(RESPONSE_CLASS_NAME)
34-
.map_err(ThrowObject::from_throwable)?
35-
.new_object([])?;
36-
unsafe {
37-
*object.as_mut_state_obj().as_mut_state() = Some(response);
38-
}
34+
let mut object = RESPONSE_CLASS.new_object([])?;
35+
*object.as_mut_state() = Some(response);
3936
Ok::<_, phper::Error>(object)
4037
});
4138

examples/http-client/src/response.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,22 @@
1111
use crate::errors::HttpClientError;
1212
use phper::{
1313
arrays::{InsertKey, ZArray},
14-
classes::{ClassEntity, Visibility},
14+
classes::{ClassEntity, StateClass, Visibility},
1515
values::ZVal,
1616
};
1717
use reqwest::blocking::Response;
1818
use std::mem::take;
1919

2020
pub const RESPONSE_CLASS_NAME: &str = "HttpClient\\Response";
2121

22+
pub static RESPONSE_CLASS: StateClass<Option<Response>> = StateClass::null();
23+
2224
pub fn make_response_class() -> ClassEntity<Option<Response>> {
2325
let mut class =
2426
ClassEntity::<Option<Response>>::new_with_default_state_constructor(RESPONSE_CLASS_NAME);
2527

28+
class.bind(&RESPONSE_CLASS);
29+
2630
class.add_method("body", Visibility::Public, |this, _arguments| {
2731
let response = take(this.as_mut_state());
2832
let response = response.ok_or(HttpClientError::ResponseHadRead)?;

phper-doc/doc/_02_quick_start/_02_write_a_simple_http_client/index.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -193,14 +193,19 @@ Now let's begin to finish the logic.
193193

194194
use phper::{
195195
alloc::ToRefOwned,
196-
classes::Visibility,
196+
classes::{StateClass, Visibility},
197197
functions::Argument,
198198
};
199199
use reqwest::blocking::{Client, ClientBuilder};
200200
use std::{mem::take, time::Duration};
201201

202202
const HTTP_CLIENT_BUILDER_CLASS_NAME: &str = "HttpClient\\HttpClientBuilder";
203+
203204
const HTTP_CLIENT_CLASS_NAME: &str = "HttpClient\\HttpClient";
205+
206+
// The static StateClass is bind to ClassEntity of HttpClient, When the class registered,
207+
// the StateClass will be initialized, so you can use it to new stateful object, etc.
208+
static HTTP_CLIENT_CLASS: StateClass<Option<Client>> = StateClass::null();
204209

205210
pub fn make_client_builder_class() -> ClassEntity<ClientBuilder> {
206211
// `new_with_default_state_constructor` means initialize the state of `ClientBuilder` as
@@ -234,10 +239,8 @@ Now let's begin to finish the logic.
234239
class.add_method("build", Visibility::Public, |this, _arguments| {
235240
let state = take(this.as_mut_state());
236241
let client = ClientBuilder::build(state).map_err(HttpClientError::Reqwest)?;
237-
let mut object = ClassEntry::from_globals(HTTP_CLIENT_CLASS_NAME)?.init_object()?;
238-
unsafe {
239-
*object.as_mut_state_obj().as_mut_state() = Some(client);
240-
}
242+
let mut object = HTTP_CLIENT_CLASS.init_object()?;
243+
*object.as_mut_state() = Some(client);
241244
Ok::<_, phper::Error>(object)
242245
});
243246

phper/src/classes.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,8 @@ impl<T> StateClass<T> {
280280
}
281281
}
282282

283+
unsafe impl<T> Sync for StateClass<T> {}
284+
283285
pub(crate) type StateConstructor = dyn Fn() -> *mut dyn Any;
284286

285287
pub(crate) type StateCloner = dyn Fn(*const dyn Any) -> *mut dyn Any;

0 commit comments

Comments
 (0)