1use crate::support::CxxVTable;
4use crate::support::Opaque;
5use std::cell::UnsafeCell;
6use std::ffi::CString;
7use std::mem::MaybeUninit;
8use std::pin::Pin;
9
10unsafe extern "C" {
11 fn crdtp__FrontendChannel__BASE__CONSTRUCT(
12 buf: *mut MaybeUninit<RawFrontendChannel>,
13 );
14
15 fn crdtp__Serializable__DELETE(this: *mut RawSerializable);
16 fn crdtp__Serializable__AppendSerialized(
17 this: *const RawSerializable,
18 out: *mut CppVecU8,
19 );
20
21 fn crdtp__Dispatchable__new(data: *const u8, len: usize)
22 -> *mut Dispatchable;
23 fn crdtp__Dispatchable__DELETE(this: *mut Dispatchable);
24 fn crdtp__Dispatchable__ok(this: *const Dispatchable) -> bool;
25 fn crdtp__Dispatchable__callId(this: *const Dispatchable) -> i32;
26 fn crdtp__Dispatchable__hasCallId(this: *const Dispatchable) -> bool;
27 fn crdtp__Dispatchable__methodLen(this: *const Dispatchable) -> usize;
28 fn crdtp__Dispatchable__methodCopy(this: *const Dispatchable, out: *mut u8);
29 fn crdtp__Dispatchable__sessionIdLen(this: *const Dispatchable) -> usize;
30 fn crdtp__Dispatchable__sessionIdCopy(
31 this: *const Dispatchable,
32 out: *mut u8,
33 );
34 fn crdtp__Dispatchable__paramsLen(this: *const Dispatchable) -> usize;
35 fn crdtp__Dispatchable__paramsCopy(this: *const Dispatchable, out: *mut u8);
36
37 fn crdtp__DispatchResponse__Success() -> *mut DispatchResponseWrapper;
38 fn crdtp__DispatchResponse__FallThrough() -> *mut DispatchResponseWrapper;
39 fn crdtp__DispatchResponse__ParseError(
40 msg: *const u8,
41 len: usize,
42 ) -> *mut DispatchResponseWrapper;
43 fn crdtp__DispatchResponse__InvalidRequest(
44 msg: *const u8,
45 len: usize,
46 ) -> *mut DispatchResponseWrapper;
47 fn crdtp__DispatchResponse__MethodNotFound(
48 msg: *const u8,
49 len: usize,
50 ) -> *mut DispatchResponseWrapper;
51 fn crdtp__DispatchResponse__InvalidParams(
52 msg: *const u8,
53 len: usize,
54 ) -> *mut DispatchResponseWrapper;
55 fn crdtp__DispatchResponse__ServerError(
56 msg: *const u8,
57 len: usize,
58 ) -> *mut DispatchResponseWrapper;
59 fn crdtp__DispatchResponse__DELETE(this: *mut DispatchResponseWrapper);
60 fn crdtp__DispatchResponse__isSuccess(
61 this: *const DispatchResponseWrapper,
62 ) -> bool;
63 fn crdtp__DispatchResponse__isError(
64 this: *const DispatchResponseWrapper,
65 ) -> bool;
66 fn crdtp__DispatchResponse__isFallThrough(
67 this: *const DispatchResponseWrapper,
68 ) -> bool;
69 fn crdtp__DispatchResponse__code(this: *const DispatchResponseWrapper)
70 -> i32;
71 fn crdtp__DispatchResponse__messageLen(
72 this: *const DispatchResponseWrapper,
73 ) -> usize;
74 fn crdtp__DispatchResponse__messageCopy(
75 this: *const DispatchResponseWrapper,
76 out: *mut u8,
77 );
78
79 fn crdtp__UberDispatcher__new(
80 channel: *mut RawFrontendChannel,
81 ) -> *mut UberDispatcher;
82 fn crdtp__UberDispatcher__DELETE(this: *mut UberDispatcher);
83 fn crdtp__UberDispatcher__channel(
84 this: *mut UberDispatcher,
85 ) -> *mut RawFrontendChannel;
86 fn crdtp__UberDispatcher__Dispatch(
87 this: *mut UberDispatcher,
88 dispatchable: *const Dispatchable,
89 ) -> *mut DispatchResultWrapper;
90
91 fn crdtp__DispatchResult__DELETE(this: *mut DispatchResultWrapper);
92 fn crdtp__DispatchResult__MethodFound(
93 this: *const DispatchResultWrapper,
94 ) -> bool;
95 fn crdtp__DispatchResult__Run(this: *mut DispatchResultWrapper);
96
97 fn crdtp__vec_u8__new() -> *mut CppVecU8;
98 fn crdtp__vec_u8__DELETE(this: *mut CppVecU8);
99 fn crdtp__vec_u8__size(this: *const CppVecU8) -> usize;
100 fn crdtp__vec_u8__copy(this: *const CppVecU8, out: *mut u8);
101
102 fn crdtp__json__ConvertJSONToCBOR(
103 json_data: *const u8,
104 json_len: usize,
105 cbor_out: *mut CppVecU8,
106 ) -> bool;
107 fn crdtp__json__ConvertCBORToJSON(
108 cbor_data: *const u8,
109 cbor_len: usize,
110 json_out: *mut CppVecU8,
111 ) -> bool;
112
113 fn crdtp__CreateErrorResponse(
114 call_id: i32,
115 response: *mut DispatchResponseWrapper,
116 ) -> *mut RawSerializable;
117 fn crdtp__CreateResponse(
118 call_id: i32,
119 params: *mut RawSerializable,
120 ) -> *mut RawSerializable;
121 fn crdtp__CreateNotification(
122 method: *const std::ffi::c_char,
123 params: *mut RawSerializable,
124 ) -> *mut RawSerializable;
125 fn crdtp__CreateErrorNotification(
126 response: *mut DispatchResponseWrapper,
127 ) -> *mut RawSerializable;
128
129 fn crdtp__DomainDispatcher__new(
130 channel: *mut RawFrontendChannel,
131 rust_dispatcher: *mut std::ffi::c_void,
132 ) -> *mut RawDomainDispatcher;
133 fn crdtp__DomainDispatcher__sendResponse(
134 this: *mut RawDomainDispatcher,
135 call_id: i32,
136 response: *mut DispatchResponseWrapper,
137 result: *mut RawSerializable,
138 );
139 fn crdtp__UberDispatcher__WireBackend(
140 uber: *mut UberDispatcher,
141 domain_data: *const u8,
142 domain_len: usize,
143 dispatcher: *mut RawDomainDispatcher,
144 );
145}
146
147#[repr(C)]
148pub struct Dispatchable(Opaque);
149
150#[repr(C)]
151struct DispatchResponseWrapper(Opaque);
152
153#[repr(C)]
154pub struct UberDispatcher(Opaque);
155
156#[repr(C)]
157struct DispatchResultWrapper(Opaque);
158
159#[repr(C)]
160struct CppVecU8(Opaque);
161
162#[repr(C)]
163struct RawSerializable(Opaque);
164
165#[repr(C)]
166struct RawDomainDispatcher(Opaque);
167
168pub struct Serializable {
169 ptr: *mut RawSerializable,
170}
171
172impl Serializable {
173 pub fn to_bytes(&self) -> Vec<u8> {
174 unsafe {
175 let vec = crdtp__vec_u8__new();
176 crdtp__Serializable__AppendSerialized(self.ptr, vec);
177 let len = crdtp__vec_u8__size(vec);
178 let mut result = vec![0u8; len];
179 crdtp__vec_u8__copy(vec, result.as_mut_ptr());
180 crdtp__vec_u8__DELETE(vec);
181 result
182 }
183 }
184
185 fn into_raw(self) -> *mut RawSerializable {
186 let ptr = self.ptr;
187 std::mem::forget(self);
188 ptr
189 }
190}
191
192impl Drop for Serializable {
193 fn drop(&mut self) {
194 unsafe {
195 crdtp__Serializable__DELETE(self.ptr);
196 }
197 }
198}
199
200impl Dispatchable {
201 pub fn new(cbor_data: &[u8]) -> Box<Self> {
202 unsafe {
203 let ptr = crdtp__Dispatchable__new(cbor_data.as_ptr(), cbor_data.len());
204 Box::from_raw(ptr)
205 }
206 }
207
208 pub fn ok(&self) -> bool {
209 unsafe { crdtp__Dispatchable__ok(self) }
210 }
211
212 pub fn call_id(&self) -> i32 {
213 unsafe { crdtp__Dispatchable__callId(self) }
214 }
215
216 pub fn has_call_id(&self) -> bool {
217 unsafe { crdtp__Dispatchable__hasCallId(self) }
218 }
219
220 pub fn method(&self) -> Vec<u8> {
221 unsafe {
222 let len = crdtp__Dispatchable__methodLen(self);
223 let mut buf = vec![0u8; len];
224 crdtp__Dispatchable__methodCopy(self, buf.as_mut_ptr());
225 buf
226 }
227 }
228
229 pub fn method_str(&self) -> String {
230 String::from_utf8_lossy(&self.method()).into_owned()
231 }
232
233 pub fn session_id(&self) -> Vec<u8> {
234 unsafe {
235 let len = crdtp__Dispatchable__sessionIdLen(self);
236 let mut buf = vec![0u8; len];
237 crdtp__Dispatchable__sessionIdCopy(self, buf.as_mut_ptr());
238 buf
239 }
240 }
241
242 pub fn params(&self) -> Vec<u8> {
243 unsafe {
244 let len = crdtp__Dispatchable__paramsLen(self);
245 let mut buf = vec![0u8; len];
246 crdtp__Dispatchable__paramsCopy(self, buf.as_mut_ptr());
247 buf
248 }
249 }
250}
251
252impl Drop for Dispatchable {
253 fn drop(&mut self) {
254 unsafe {
255 crdtp__Dispatchable__DELETE(self);
256 }
257 }
258}
259
260pub struct DispatchResponse {
261 ptr: *mut DispatchResponseWrapper,
262}
263
264impl DispatchResponse {
265 pub fn success() -> Self {
266 unsafe {
267 Self {
268 ptr: crdtp__DispatchResponse__Success(),
269 }
270 }
271 }
272
273 pub fn fall_through() -> Self {
274 unsafe {
275 Self {
276 ptr: crdtp__DispatchResponse__FallThrough(),
277 }
278 }
279 }
280
281 pub fn parse_error(message: &str) -> Self {
282 unsafe {
283 Self {
284 ptr: crdtp__DispatchResponse__ParseError(
285 message.as_ptr(),
286 message.len(),
287 ),
288 }
289 }
290 }
291
292 pub fn invalid_request(message: &str) -> Self {
293 unsafe {
294 Self {
295 ptr: crdtp__DispatchResponse__InvalidRequest(
296 message.as_ptr(),
297 message.len(),
298 ),
299 }
300 }
301 }
302
303 pub fn method_not_found(message: &str) -> Self {
304 unsafe {
305 Self {
306 ptr: crdtp__DispatchResponse__MethodNotFound(
307 message.as_ptr(),
308 message.len(),
309 ),
310 }
311 }
312 }
313
314 pub fn invalid_params(message: &str) -> Self {
315 unsafe {
316 Self {
317 ptr: crdtp__DispatchResponse__InvalidParams(
318 message.as_ptr(),
319 message.len(),
320 ),
321 }
322 }
323 }
324
325 pub fn server_error(message: &str) -> Self {
326 unsafe {
327 Self {
328 ptr: crdtp__DispatchResponse__ServerError(
329 message.as_ptr(),
330 message.len(),
331 ),
332 }
333 }
334 }
335
336 pub fn is_success(&self) -> bool {
337 unsafe { crdtp__DispatchResponse__isSuccess(self.ptr) }
338 }
339
340 pub fn is_error(&self) -> bool {
341 unsafe { crdtp__DispatchResponse__isError(self.ptr) }
342 }
343
344 pub fn is_fall_through(&self) -> bool {
346 unsafe { crdtp__DispatchResponse__isFallThrough(self.ptr) }
347 }
348
349 pub fn code(&self) -> i32 {
351 unsafe { crdtp__DispatchResponse__code(self.ptr) }
352 }
353
354 pub fn message(&self) -> String {
356 unsafe {
357 let len = crdtp__DispatchResponse__messageLen(self.ptr);
358 let mut buf = vec![0u8; len];
359 crdtp__DispatchResponse__messageCopy(self.ptr, buf.as_mut_ptr());
360 String::from_utf8_lossy(&buf).into_owned()
361 }
362 }
363
364 fn into_raw(self) -> *mut DispatchResponseWrapper {
365 let ptr = self.ptr;
366 std::mem::forget(self);
367 ptr
368 }
369}
370
371impl Drop for DispatchResponse {
372 fn drop(&mut self) {
373 unsafe {
374 crdtp__DispatchResponse__DELETE(self.ptr);
375 }
376 }
377}
378
379pub trait FrontendChannelImpl {
381 fn send_protocol_response(&mut self, call_id: i32, message: Serializable);
383 fn send_protocol_notification(&mut self, message: Serializable);
385 fn fall_through(&mut self, call_id: i32, method: &[u8], message: &[u8]);
387 fn flush_protocol_notifications(&mut self);
389}
390
391#[repr(C)]
392struct RawFrontendChannel {
393 _cxx_vtable: CxxVTable,
394}
395
396pub struct FrontendChannel {
398 raw: UnsafeCell<RawFrontendChannel>,
399 imp: Box<dyn FrontendChannelImpl>,
400}
401
402impl FrontendChannel {
403 pub fn new(imp: Box<dyn FrontendChannelImpl>) -> Pin<Box<Self>> {
405 let channel = Box::new(Self {
406 raw: UnsafeCell::new(unsafe { MaybeUninit::zeroed().assume_init() }),
407 imp,
408 });
409 unsafe {
410 crdtp__FrontendChannel__BASE__CONSTRUCT(
411 channel.raw.get() as *mut _ as *mut MaybeUninit<RawFrontendChannel>
412 );
413 }
414 Box::into_pin(channel)
415 }
416
417 fn raw_ptr(&self) -> *mut RawFrontendChannel {
418 self.raw.get()
419 }
420
421 unsafe fn from_raw<'a>(ptr: *mut RawFrontendChannel) -> &'a mut Self {
422 unsafe {
423 let channel_ptr = ptr as *mut u8;
424 let offset = std::mem::offset_of!(FrontendChannel, raw);
425 let self_ptr = channel_ptr.sub(offset) as *mut Self;
426 &mut *self_ptr
427 }
428 }
429}
430
431#[unsafe(no_mangle)]
432unsafe extern "C" fn crdtp__FrontendChannel__BASE__sendProtocolResponse(
433 this: *mut RawFrontendChannel,
434 call_id: i32,
435 message: *mut RawSerializable,
436) {
437 unsafe {
438 let channel = FrontendChannel::from_raw(this);
439 let msg = Serializable { ptr: message };
440 channel.imp.send_protocol_response(call_id, msg);
441 }
442}
443
444#[unsafe(no_mangle)]
445unsafe extern "C" fn crdtp__FrontendChannel__BASE__sendProtocolNotification(
446 this: *mut RawFrontendChannel,
447 message: *mut RawSerializable,
448) {
449 unsafe {
450 let channel = FrontendChannel::from_raw(this);
451 let msg = Serializable { ptr: message };
452 channel.imp.send_protocol_notification(msg);
453 }
454}
455
456#[unsafe(no_mangle)]
457unsafe extern "C" fn crdtp__FrontendChannel__BASE__fallThrough(
458 this: *mut RawFrontendChannel,
459 call_id: i32,
460 method_data: *const u8,
461 method_len: usize,
462 message_data: *const u8,
463 message_len: usize,
464) {
465 unsafe {
466 let channel = FrontendChannel::from_raw(this);
467 let method = std::slice::from_raw_parts(method_data, method_len);
468 let message = std::slice::from_raw_parts(message_data, message_len);
469 channel.imp.fall_through(call_id, method, message);
470 }
471}
472
473#[unsafe(no_mangle)]
474unsafe extern "C" fn crdtp__FrontendChannel__BASE__flushProtocolNotifications(
475 this: *mut RawFrontendChannel,
476) {
477 unsafe {
478 let channel = FrontendChannel::from_raw(this);
479 channel.imp.flush_protocol_notifications();
480 }
481}
482
483pub struct DispatchResult {
485 ptr: *mut DispatchResultWrapper,
486}
487
488impl DispatchResult {
489 pub fn method_found(&self) -> bool {
491 unsafe { crdtp__DispatchResult__MethodFound(self.ptr) }
492 }
493
494 pub fn run(self) {
496 unsafe {
497 crdtp__DispatchResult__Run(self.ptr);
498 }
499 }
501}
502
503impl Drop for DispatchResult {
504 fn drop(&mut self) {
505 unsafe {
506 crdtp__DispatchResult__DELETE(self.ptr);
507 }
508 }
509}
510
511impl UberDispatcher {
512 pub fn new(channel: &Pin<Box<FrontendChannel>>) -> Box<Self> {
514 unsafe {
515 let ptr = crdtp__UberDispatcher__new(channel.raw_ptr());
516 Box::from_raw(ptr)
517 }
518 }
519
520 pub fn dispatch(&mut self, dispatchable: &Dispatchable) -> DispatchResult {
522 unsafe {
523 let ptr = crdtp__UberDispatcher__Dispatch(self, dispatchable);
524 DispatchResult { ptr }
525 }
526 }
527}
528
529impl Drop for UberDispatcher {
530 fn drop(&mut self) {
531 unsafe {
532 crdtp__UberDispatcher__DELETE(self);
533 }
534 }
535}
536
537pub fn json_to_cbor(json: &[u8]) -> Option<Vec<u8>> {
539 unsafe {
540 let vec = crdtp__vec_u8__new();
541 let ok = crdtp__json__ConvertJSONToCBOR(json.as_ptr(), json.len(), vec);
542 if ok {
543 let len = crdtp__vec_u8__size(vec);
544 let mut result = vec![0u8; len];
545 crdtp__vec_u8__copy(vec, result.as_mut_ptr());
546 crdtp__vec_u8__DELETE(vec);
547 Some(result)
548 } else {
549 crdtp__vec_u8__DELETE(vec);
550 None
551 }
552 }
553}
554
555pub fn cbor_to_json(cbor: &[u8]) -> Option<Vec<u8>> {
557 unsafe {
558 let vec = crdtp__vec_u8__new();
559 let ok = crdtp__json__ConvertCBORToJSON(cbor.as_ptr(), cbor.len(), vec);
560 if ok {
561 let len = crdtp__vec_u8__size(vec);
562 let mut result = vec![0u8; len];
563 crdtp__vec_u8__copy(vec, result.as_mut_ptr());
564 crdtp__vec_u8__DELETE(vec);
565 Some(result)
566 } else {
567 crdtp__vec_u8__DELETE(vec);
568 None
569 }
570 }
571}
572
573pub fn create_error_response(
575 call_id: i32,
576 response: DispatchResponse,
577) -> Serializable {
578 unsafe {
579 let ptr = crdtp__CreateErrorResponse(call_id, response.into_raw());
580 Serializable { ptr }
581 }
582}
583
584pub fn create_error_notification(response: DispatchResponse) -> Serializable {
586 unsafe {
587 let ptr = crdtp__CreateErrorNotification(response.into_raw());
588 Serializable { ptr }
589 }
590}
591
592pub fn create_response(
594 call_id: i32,
595 params: Option<Serializable>,
596) -> Serializable {
597 unsafe {
598 let params_ptr = match params {
599 Some(p) => p.into_raw(),
600 None => std::ptr::null_mut(),
601 };
602 let ptr = crdtp__CreateResponse(call_id, params_ptr);
603 Serializable { ptr }
604 }
605}
606
607pub fn create_notification(
612 method: &str,
613 params: Option<Serializable>,
614) -> Serializable {
615 unsafe {
616 let method_cstr =
617 CString::new(method).expect("method name must not contain null bytes");
618 let params_ptr = match params {
619 Some(p) => p.into_raw(),
620 None => std::ptr::null_mut(),
621 };
622 let ptr = crdtp__CreateNotification(method_cstr.as_ptr(), params_ptr);
623 Serializable { ptr }
624 }
625}
626
627pub trait DomainDispatcherImpl {
635 fn dispatch(
636 &mut self,
637 command: &[u8],
638 dispatchable: Option<&Dispatchable>,
639 handle: &DomainDispatcherHandle,
640 ) -> bool;
641}
642
643pub struct DomainDispatcherHandle {
645 ptr: *mut RawDomainDispatcher,
646}
647
648impl DomainDispatcherHandle {
649 pub fn send_response(
651 &self,
652 call_id: i32,
653 response: DispatchResponse,
654 result: Option<Serializable>,
655 ) {
656 unsafe {
657 let result_ptr = match result {
658 Some(r) => r.into_raw(),
659 None => std::ptr::null_mut(),
660 };
661 crdtp__DomainDispatcher__sendResponse(
662 self.ptr,
663 call_id,
664 response.into_raw(),
665 result_ptr,
666 );
667 }
668 }
669}
670
671struct DomainDispatcherData {
679 ptr: *mut RawDomainDispatcher,
680 imp: Box<dyn DomainDispatcherImpl>,
681 domain_bytes: Vec<u8>,
682}
683
684pub struct DomainDispatcher;
685
686impl DomainDispatcher {
687 pub fn wire(
693 uber: &mut UberDispatcher,
694 domain: &str,
695 imp: Box<dyn DomainDispatcherImpl>,
696 ) {
697 let domain_bytes = domain.as_bytes().to_vec();
700
701 let mut dd = Box::new(DomainDispatcherData {
702 ptr: std::ptr::null_mut(),
703 imp,
704 domain_bytes,
705 });
706
707 unsafe {
708 let rust_ptr =
709 &mut *dd as *mut DomainDispatcherData as *mut std::ffi::c_void;
710 let channel = crdtp__UberDispatcher__channel(uber);
711 let raw = crdtp__DomainDispatcher__new(channel, rust_ptr);
712 dd.ptr = raw;
713
714 crdtp__UberDispatcher__WireBackend(
715 uber,
716 dd.domain_bytes.as_ptr(),
717 dd.domain_bytes.len(),
718 raw,
719 );
720 }
721
722 let _ = Box::into_raw(dd);
725 }
726}
727
728#[unsafe(no_mangle)]
729unsafe extern "C" fn crdtp__DomainDispatcher__BASE__Dispatch(
730 rust_dispatcher: *mut std::ffi::c_void,
731 command_data: *const u8,
732 command_len: usize,
733 dispatchable: *const Dispatchable,
734) -> bool {
735 unsafe {
736 let dd = &mut *(rust_dispatcher as *mut DomainDispatcherData);
737 let command = std::slice::from_raw_parts(command_data, command_len);
738 let handle = DomainDispatcherHandle { ptr: dd.ptr };
739 let dispatchable_ref = if dispatchable.is_null() {
740 None
741 } else {
742 Some(&*dispatchable)
743 };
744 dd.imp.dispatch(command, dispatchable_ref, &handle)
745 }
746}
747
748#[unsafe(no_mangle)]
749unsafe extern "C" fn crdtp__DomainDispatcher__BASE__Drop(
750 rust_dispatcher: *mut std::ffi::c_void,
751) {
752 unsafe {
753 drop(Box::from_raw(rust_dispatcher as *mut DomainDispatcherData));
754 }
755}