1 use crate::{
2 gatt::server::att_database::AttDatabase,
3 packets::{
4 AttChild, AttErrorResponseBuilder, AttOpcode, AttWriteRequestView, AttWriteResponseBuilder,
5 },
6 };
7
handle_write_request<T: AttDatabase>( request: AttWriteRequestView<'_>, db: &T, ) -> AttChild8 pub async fn handle_write_request<T: AttDatabase>(
9 request: AttWriteRequestView<'_>,
10 db: &T,
11 ) -> AttChild {
12 let handle = request.get_handle().into();
13 match db.write_attribute(handle, request.get_value()).await {
14 Ok(()) => AttWriteResponseBuilder {}.into(),
15 Err(error_code) => AttErrorResponseBuilder {
16 opcode_in_error: AttOpcode::WRITE_REQUEST,
17 handle_in_error: handle.into(),
18 error_code,
19 }
20 .into(),
21 }
22 }
23
24 #[cfg(test)]
25 mod test {
26 use super::*;
27
28 use tokio_test::block_on;
29
30 use crate::{
31 core::uuid::Uuid,
32 gatt::{
33 ids::AttHandle,
34 server::{
35 att_database::{AttAttribute, AttDatabase},
36 gatt_database::AttPermissions,
37 test::test_att_db::TestAttDatabase,
38 },
39 },
40 packets::{
41 AttAttributeDataChild, AttChild, AttErrorCode, AttErrorResponseBuilder,
42 AttWriteRequestBuilder, AttWriteResponseBuilder,
43 },
44 utils::packet::{build_att_data, build_view_or_crash},
45 };
46
47 #[test]
test_successful_write()48 fn test_successful_write() {
49 // arrange: db with one writable attribute
50 let db = TestAttDatabase::new(vec![(
51 AttAttribute {
52 handle: AttHandle(1),
53 type_: Uuid::new(0x1234),
54 permissions: AttPermissions::READABLE | AttPermissions::WRITABLE_WITH_RESPONSE,
55 },
56 vec![],
57 )]);
58 let data = AttAttributeDataChild::RawData([1, 2].into());
59
60 // act: write to the attribute
61 let att_view = build_view_or_crash(AttWriteRequestBuilder {
62 handle: AttHandle(1).into(),
63 value: build_att_data(data.clone()),
64 });
65 let resp = block_on(handle_write_request(att_view.view(), &db));
66
67 // assert: that the write succeeded
68 assert_eq!(resp, AttChild::from(AttWriteResponseBuilder {}));
69 assert_eq!(block_on(db.read_attribute(AttHandle(1))).unwrap(), data);
70 }
71
72 #[test]
test_failed_write()73 fn test_failed_write() {
74 // arrange: db with no writable attributes
75 let db = TestAttDatabase::new(vec![(
76 AttAttribute {
77 handle: AttHandle(1),
78 type_: Uuid::new(0x1234),
79 permissions: AttPermissions::READABLE,
80 },
81 vec![],
82 )]);
83 // act: write to the attribute
84 let att_view = build_view_or_crash(AttWriteRequestBuilder {
85 handle: AttHandle(1).into(),
86 value: build_att_data(AttAttributeDataChild::RawData([1, 2].into())),
87 });
88 let resp = block_on(handle_write_request(att_view.view(), &db));
89
90 // assert: that the write failed
91 assert_eq!(
92 resp,
93 AttChild::from(AttErrorResponseBuilder {
94 opcode_in_error: AttOpcode::WRITE_REQUEST,
95 handle_in_error: AttHandle(1).into(),
96 error_code: AttErrorCode::WRITE_NOT_PERMITTED
97 })
98 );
99 }
100 }
101