1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//! Collection of [RTCIceServer][1]s.
//!
//! [1]: https://w3.org/TR/webrtc#rtciceserver-dictionary

use dart_sys::Dart_Handle;
use medea_client_api_proto::IceServer;
use medea_macro::dart_bridge;

use crate::platform::utils::{handle::DartHandle, string_into_c_str};

#[dart_bridge("flutter/lib/src/native/platform/ice_servers.g.dart")]
mod ice_servers {
    use std::{os::raw::c_char, ptr};

    use dart_sys::Dart_Handle;

    use crate::{api::DartValueArg, platform::Error};

    extern "C" {
        /// Returns a [`Dart_Handle`] to the newly created empty `List` with
        /// `IceServer`s.
        pub fn init() -> Result<Dart_Handle, Error>;

        /// Adds an `IceServer` to the provided `List`.
        pub fn add(
            list: Dart_Handle,
            url: ptr::NonNull<c_char>,
            username: DartValueArg<String>,
            credentials: DartValueArg<String>,
        ) -> Result<(), Error>;
    }
}

/// Collection of [RTCIceServer][1]s.
///
/// [1]: https://w3.org/TR/webrtc#rtciceserver-dictionary
#[derive(Debug)]
pub struct RtcIceServers(DartHandle);

impl RtcIceServers {
    /// Returns [`Dart_Handle`] of these [`RtcIceServers`].
    #[must_use]
    pub fn get_handle(&self) -> Dart_Handle {
        self.0.get()
    }
}

#[expect(clippy::fallible_impl_from, reason = "FFI error is unexpected")]
impl<I> From<I> for RtcIceServers
where
    I: IntoIterator<Item = IceServer>,
{
    fn from(servers: I) -> Self {
        let ice_servers = unsafe { ice_servers::init() }.unwrap();
        let ice_servers = unsafe { DartHandle::new(ice_servers) };
        for srv in servers {
            for url in srv.urls {
                unsafe {
                    ice_servers::add(
                        ice_servers.get(),
                        string_into_c_str(url),
                        srv.username.clone().into(),
                        srv.credential.clone().into(),
                    )
                }
                .unwrap();
            }
        }
        Self(ice_servers)
    }
}